天天看點

React之setState詳解

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,這樣會使試圖不更新。如下面:

React之setState詳解

造成這樣的原因是,在 useState 的 dispatchAction 的處理邏輯中。會淺比兩次的 state,發現 state 相同,就不會開啟更新排程任務,demo 中兩次 state 指向了相同的記憶體空間,是以預設 state 是相等的,就不會發生試圖更新。 如要解決,則将 dispatchState 改成 dispatchState({...state}) 可以從根本解決問題。 結果就是淺拷貝對象,重新申請了一個記憶體空間。

useState 與 setState 有什麼不同?

答:

相同點: setState 合 useState 更新視圖,底層都調用了 scheduleUpdateOnFiber 方法。而且事件驅動情況下都有批量更新規則。

不同點:

繼續閱讀