1. 使用
const [state, setState] = useState(initialState);
setState(newState);
因?yàn)閞eact是函數(shù)式編程,useState函數(shù)接收一個(gè)初始化參數(shù)initialState,其返回值用數(shù)組解構(gòu)倆個(gè)參數(shù),state是初始化的state,以及更新state的函數(shù)setState. 在初始渲染期間,返回的狀態(tài) (state) 與傳入的第一個(gè)參數(shù) (initialState) 值相同。setState 函數(shù)用于更新 state。它接收一個(gè)新的 state 值并將組件的一次重新渲染加入隊(duì)列。在后續(xù)的重新渲染中,useState 返回的第一個(gè)值將始終是更新后最新的 state。
注意: React 會(huì)確保 setState 函數(shù)的標(biāo)識(shí)是穩(wěn)定的,并且不會(huì)在組件重新渲染時(shí)發(fā)生變化。這就是為什么可以安全地從 useEffect 或 useCallback 的依賴(lài)列表中省略 setState
2.函數(shù)式更新
如果新的 state 依賴(lài)之前的state,可以將函數(shù)傳遞給 setState。該函數(shù)將接收先前的 state,并返回一個(gè)更新后的值。
如果你的更新函數(shù)返回值與當(dāng)前 state 完全相同,則隨后的重渲染會(huì)被完全跳過(guò)。
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</>
);
}
與 class 組件中的 setState 方法不同,useState 不會(huì)自動(dòng)合并更新對(duì)象。你可以用函數(shù)式的 setState 結(jié)合展開(kāi)運(yùn)算符來(lái)達(dá)到合并更新對(duì)象的效果。
setState(prevState => {
// 也可以使用 Object.assign
return {...prevState, ...updatedValues};
});
3.惰性初始 state
initialState 參數(shù)只會(huì)在組件的初始渲染中起作用,后續(xù)渲染時(shí)會(huì)被忽略。如果初始 state 需要通過(guò)復(fù)雜計(jì)算獲得,則可以傳入一個(gè)函數(shù),在函數(shù)中計(jì)算并返回初始的 state,此函數(shù)只在初始渲染時(shí)被調(diào)用:
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});
注意
1.useState()中的參數(shù)可以使用任意類(lèi)型(string,number,object,function等)作為初始值。
2.class組件調(diào)用setState,是將現(xiàn)在的數(shù)據(jù)與之前的state數(shù)據(jù)進(jìn)行合并然后返回一個(gè)新?tīng)顟B(tài),而hooks調(diào)用setState方法是將之前的state數(shù)據(jù)進(jìn)行替換,返回一個(gè)新?tīng)顟B(tài).
3.在開(kāi)發(fā)中,無(wú)論useState()函數(shù)被調(diào)用了多少次,他們之前都是互相不影響,都是相互獨(dú)立的。那么這是如何做到的呢?react會(huì)根據(jù)useState的順序來(lái)規(guī)定的。在react實(shí)現(xiàn)的內(nèi)部聲明了一個(gè)數(shù)組,按照其useState()函數(shù)調(diào)用的順序,來(lái)保存其數(shù)據(jù),所以一定要在函數(shù)的外層調(diào)用useState(),不要在if...else,for循環(huán),子函數(shù)中調(diào)用useState()。因?yàn)閞eact函數(shù)共享一個(gè)保存數(shù)據(jù)的數(shù)組,那么也會(huì)對(duì)其他的函數(shù)組件有影響。Capture Value” 特性的產(chǎn)生是在于每一次 ReRender 的時(shí)候,都是重新去執(zhí)行函數(shù)組件了,對(duì)于之前已經(jīng)執(zhí)行過(guò)的函數(shù)組件,并不會(huì)做任何操作。