React hooks使用規(guī)則和作用
使用hooks理由:
- 高階組件為了復(fù)用,導(dǎo)致代碼層級復(fù)雜
- 生命周期的復(fù)雜
- 寫成functional組件,無狀態(tài)組件,因?yàn)樾枰獱顟B(tài),又改成了class,成本高
hooks使用規(guī)則
- 只能在函數(shù)最外層調(diào)用 Hook。不要在循環(huán)、條件判斷或者子函數(shù)中調(diào)用。
- 只能在 React 的函數(shù)組件中調(diào)用 Hook。不要在其他 JavaScript 函數(shù)中調(diào)用。(還有一個地方可以調(diào)用 Hook —— 就是自定義的 Hook 中
useState(保存組件狀態(tài))
語法:
//導(dǎo)入 useState
import React,{useState}from 'react'
..........................................
const [state,setState] = useState(initialState)
內(nèi)容
- 返回一個state,以及修改state的函數(shù),在初始渲染期間,返回的狀態(tài)state與傳入的第一個參數(shù)值 initialState值相同
- setState函數(shù)用于更新 state。它接收一個新的參數(shù),并將組件的一次重新渲染加入隊(duì)列。
- 可以在一個組件中多次使用
修改state
//setState(newState)
setState('123')
useEffect(處理副作用)
使用useEffect
在函數(shù)組件中,要知道這個組件現(xiàn)在處在那個生命周期,比較麻煩,甚至有點(diǎn)無從下手,這時候我們就可以使用hook中的useEffect()
注意:
- Function Component不存在生命周期,所以不要把Class Component 的生命周期概念搬過來試圖對號入座
- 默認(rèn)情況下,useEffect會在第一次渲染之后和每次更新之前都會執(zhí)行
語法
useEffect(()=>{
.........
},[依賴;空數(shù)組,表示不依賴])
//依賴:在useEffect函數(shù)中使用的狀態(tài)
注意:如果明明使用了某個變量,卻沒有申明在依賴中,那么當(dāng)依賴的變量改變時,useEffect也不會再次執(zhí)行,控制臺會報警告
清除effect
組件卸載時需要清除effect創(chuàng)建的如計(jì)時器或請閱等資源,useEffect函數(shù)需要返回一個清除函數(shù)即可
useEffect(()=>{
//組件掛載創(chuàng)建計(jì)時器
var timer = setInterval(()=>{
console.log('111');
},1000)
........
return ()=>{
//清除計(jì)時器 若無依賴時組件銷毀
clearInterval(timer)
}
},[])
useCallback(記憶函數(shù))
防止因?yàn)榻M件重新渲染,導(dǎo)致方法被重新創(chuàng)建,起到緩存作用,只有第二個參數(shù)變化了,才能重新聲明一次
語法
var handleClick = useCallback(
()=>{
console.log(name)
},
[name]
)
<button onClick={()=>handleClick()}>hello</button>
內(nèi)容
- 當(dāng)依賴不改變時,方法不會被重建;當(dāng)只有當(dāng)依賴(name)發(fā)生改變時,這個函數(shù)才會被重新創(chuàng)建
- 如果傳入空數(shù)組,name就是第一次創(chuàng)建后就被緩存,name后期即使改變,拿到的還是老的name
- 如果不傳第二個參數(shù),每次都會被重新聲明一次,拿到的就是最新的name
useMemo(記憶組件)
useCallback常用記憶事件函數(shù),生成記憶后的事件函數(shù)并傳遞給子組件使用。而useMemo更適合經(jīng)過函數(shù)計(jì)算得到一個確定的值,比如記憶組件
useCallback的功能完全可以由useMemo取代
useMemo(() => fn,inputs)
區(qū)別:useCallback不會執(zhí)行第一個參數(shù)函數(shù),而是將他返回給你,而useMemo會執(zhí)行第一個函數(shù)并且將函數(shù)執(zhí)行結(jié)果返回給你
useRef(保存引用值)
//相當(dāng)于React.createRef()
const mytext = useRef()
................
<input ref={mytext}></input>
useContext
語法
const GlobalContext = React.createContext()//創(chuàng)建context對象
內(nèi)容
??????收一個context對象(React.createContext的返回值)并返回該context的當(dāng)前值。當(dāng)前的context值由上次組件中距離當(dāng)前組件最近的 的value *<GlobalContext.Provider> *的value prop決定
實(shí)例
//創(chuàng)建context對象
const GlobalContext = React.createContext()//創(chuàng)建context對象
..................................
//GlobalContext.Provider的value
<GlobalContext.Provider value={{
"call":"打電話"
}}>
//GlobalContext.Consumer通過context獲得value
Function FilmDetail(){
const value = useContext(GlobalContext)
return(
<div className="filmDetail">
detail-{value.info}
</div>
)
}
useReducer
可以在外部管理狀態(tài),只能在函數(shù)組件中調(diào)用
語法
定義useReducer
組件內(nèi)部: //intialState初始狀態(tài)值 state拿到狀態(tài)值,dispatch改變狀態(tài) const [state,dispatch] = useReducer(reducer,intialState)
定義在外部處理函數(shù)
//處理函數(shù)
const reducer=(prevState,action)=>{
//prevState--老的狀態(tài)
//action--dispatch內(nèi)對象
return prevState/newState
}
??????return 出新狀態(tài) 組件內(nèi)部即可通過 state獲得全新的狀態(tài)
定義在外部的狀態(tài)
組件外部:
//定義在外部的狀態(tài)
const intialState={
//放入初始狀態(tài)值
}
useContext與useReducer實(shí)現(xiàn)跨組件傳值
實(shí)現(xiàn)的效果

在App父組件中使用useReducter在外部管理所有子組件的狀態(tài),使用useContext將dispatch處理函數(shù)以及initailState狀態(tài)傳遞給子組件(Child1,Child2,Child3),Child1使用useContext獲得傳入的dispatch,Child2、Child3獲得傳入的state,此時Child1觸發(fā)dispatch()來改變state的值(a、b),而后Child2、Child3將獲得Child1修改后的最新的state值
引入useContext和useReducer
import React,{useReducer,useContext}from 'react'
//創(chuàng)建context
const GlobalContext = React.createContext()//創(chuàng)建context對象
useReducer實(shí)現(xiàn)使用外部狀態(tài)管理數(shù)據(jù),useContext實(shí)現(xiàn)組件間傳數(shù)據(jù)
定義外部狀態(tài)及處理函數(shù)
const initailState = {
a:'1111',
b:'1111'
}
const reducer = (prevState,action)=>{
let newState = {...prevState}
switch(action.type){
case "change-a":
newState.a = action.value
return newState
case "change-b":
newState.b = action.value
return newState
default:
return prevState
}
}
action為接收到的diapatch函數(shù),switch語句是根據(jù)dispatch中的type值的不同,修改a、b(不能直接修改)
父組件
export default function App() {
const [state,dispatch] = useReducer(reducer,initailState)
return (
<GlobalContext.Provider value={
{
state,
dispatch
}
}>
<div>
<Child1></Child1>
<Child2></Child2>
<Child3></Child3>
</div>
</GlobalContext.Provider>
)
}
Child1獲得dispatch,Child2、Child3獲得state
Child1修改state
function Child1(){
const {dispatch} = useContext(GlobalContext)
return(
<div style={{background:'gray'}}>
<button onClick={()=>{
dispatch({
type:"change-a",
value:'22222'
})
}}>改變a</button>
<button onClick={()=>{
dispatch({
type:"change-b",
value:'33333'
})
}}>改變b</button>
</div>
)
}
觸發(fā)dispatch函數(shù),傳入reducer,實(shí)現(xiàn)間接修改state
Child2、Child3獲得最新的state
function Child2(){
const {state} = useContext(GlobalContext)
return(
<div style={{background:'yellow'}}>
child2-{state.a}
</div>
)
}
function Child3(){
const {state} = useContext(GlobalContext)
return(
<div style={{background:'blue'}}>
child3-{state.b}
</div>
)
}
自定義hooks
當(dāng)我們想在兩個函數(shù)之間共享邏輯時,我們會把它提取到第三個函數(shù)中
只抽出邏輯,不改變渲染頁面
? 注意:必須以use開頭,不遵循的話,由于無法判斷某個函數(shù)是否包含對其內(nèi)部Hook的調(diào)用,React將無法自動檢查你的Hook是否違反了Hook的規(guī)則
到此這篇關(guān)于React hooks使用規(guī)則和作用的文章就介紹到這了,更多相關(guān)React hooks內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react-native組件中NavigatorIOS和ListView結(jié)合使用的方法
這篇文章主要給大家介紹了關(guān)于react-native組件中NavigatorIOS和ListView結(jié)合使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09
React 如何使用時間戳計(jì)算得到開始和結(jié)束時間戳
這篇文章主要介紹了React 如何拿時間戳計(jì)算得到開始和結(jié)束時間戳,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09

