React 項目中的 UI 的改變來源于 State 改變,類元件中 setState 是更新元件,渲染視圖的主要方式:
基本用法
setState(obj, callback)
setState 的第一個參數: 當 obj 為一個對象的時候,則為即将合并的 state,如何 obj 是一個函數,那麼目前元件的 state 和 props 将作為參數,傳回值用于 合并新的 state。
setState 的第二個參數:當 callback 為一個函數,函數執行上下文中可以擷取目前 setState 更新後的最新 state 的值,可以作為以來 state 變化的副作用函數,可以 用來做一些基本的 DOM 操作等。
// 第一個參數為function類型的時候
this.setState((state, props) => {
return { number: 1 }
})
// 第一個參數為object類型的時候
this.setState({ number: 1 }, () => {
console.log(this.state.number) // 擷取最新的number
})
如何監聽State變化?
. 在類元件中的 state 中,有第二個 callback 或者是在生命周期的 componentDidUpdate 中可以檢測監聽到 state 改變或是元件更新、 b. 那麼在函數元件中,如何怎麼監聽 state 變化呢?這時候就需要 useEffect 出場,通常可以把 state 作為依賴項傳入 useEffect 第二個參數 deps,但是 注意 useEffect 初始化會預設執行一次。
export defailt function Index(props) {
const [number,setNumber] = React.useState(0)
React.useEffect(() => {
console.log("監聽number變化,此時的number 是"+ number)
},[number])
const handleClidk = () => {
// 最高的優先級
ReactDOM.flushSync((0 => {
setNumber(2)
}))
//批量更新
setNumber(1)
// 稍後更新,批量更新規則被打破
setTimeout(() => {
setNumber(3)
})
console.log(number)
return <div>
<span>{number}</span>
<button onClick={handleClick}>number++</button>
</div>
}
}
useState 注意事項:
在使用 useState 的 dispatchAction 更新 state 的時候,記得不要傳入相同的 state,這樣會使試圖不更新。如下面:
造成這樣的原因是,在 useState 的 dispatchAction 的處理邏輯中。會淺比兩次的 state,發現 state 相同,就不會開啟更新排程任務,demo 中兩次 state 指向了相同的記憶體空間,是以預設 state 是相等的,就不會發生試圖更新。 如要解決,則将 dispatchState 改成 dispatchState({...state}) 可以從根本解決問題。 結果就是淺拷貝對象,重新申請了一個記憶體空間。
useState 與 setState 有什麼不同?
答:
相同點: setState 合 useState 更新視圖,底層都調用了 scheduleUpdateOnFiber 方法。而且事件驅動情況下都有批量更新規則。
不同點: