React觀察日記-useState
觀察到的 USESTATE 觸發機制
- 元件自己 setState
- 父元件 setState
- 父元件 state 用 props 傳給子元件 setState
- 一次寫多個 setState
元件自己 setState
- 如果前後 state 不一樣觸發重新 render
- state 不一樣的定義
- 如果是 Reference type 的資料類型,只要參照一樣就算裡面的值更新還是一樣的 state
* 如果是Reference type 的資料類型,修改同一個參照後 setState 不會觸發 render,但下次如果有同個元件的 state 更新觸發 rerender,剛剛修改同一個參照的資料也會更新
- 如果是 Reference type 的資料類型,只要參照一樣就算裡面的值更新還是一樣的 state
- 如果是 Primitive type 的資料類型,只要值不一樣就算
- state 不一樣的定義
- 重新 render 只會在自己這個元件,不會觸發其他元件 render
父元件 setState
- setState 之後
- 父元件更新
- 父元件更新會觸發所有子元件 rerender
- 父元件 setState 如果沒有觸發重新 render,子元件也不會重新 render
- 父元件更新
父元件 state 用 props 傳給子元件 setState
- 子元件 setState 之後
- 父元件更新
- 同父元件 setState
- 需要注意如果傳的 props 是 Reference type
- 子元件如果只有更新值,沒有更新 Reference,畫面不會更新,要等到下次這個子元件重新render之後,子元件更新後的 props 才會顯示到畫面上,而且父元件的 state還是會是舊的,畫面上也是舊的,因為並沒有觸發父元件重新render
- 父元件更新
父元件 state 用 props 傳給子元件 setState
const [conterA, setCounter] = useState(0);
const pendingTripleAdd = (): void => {
setCounter(conterA + 1);
setCounter(conterA + 1);
setCounter(conterA + 1);
};
- 上面的 setState 只會觸發一次,所以結果會是 conterA === 1
- 下面的 setState 會觸發三次,所以結果會是 conterA === 3
const [conterA, setCounter] = useState(0);
const pendingTripleAdd = (): void => {
setCounter((conterA) => conterA + 1);
setCounter((conterA) => conterA + 1);
setCounter((conterA) => conterA + 1);
};
關於官網總結
- setState 會要求新的渲染
- React將狀態存儲在組件外部,就像放在一個架子上
- 當您呼叫useState時,React會給您該渲染的狀態快照
- 變量和事件處理程序不會“存活”於重新渲染中。每次渲染都有自己的事件處理程序
- 每次渲染(及其中的函數)都會始終“看到”React給該渲染的狀態快照
- 您可以在事件處理程序中進行心理上的替換狀態,就像您思考呈現的JSX一樣
- 過去創建的事件處理程序具有它們所創建的渲染中的狀態值
排隊 (Queueing) 一系列的狀態更新
設置狀態不會改變現有渲染中的變量,而是要求一個新的渲染。
React在事件處理程序完成運行之後處理狀態更新。這就是所謂的批次處理。 要在一個事件中多次更新某個狀態,可以使用setNumber(n => n + 1)更新器功能。
個人總結
react 元件渲染其實就是 呼叫 render(class 元件) function (函式型元件),當下會產生類似 snapShot 的動作(不確定與 virturl dom 的關係),下次有 event 觸發 setState 時,會觸發batch 批處理(react 對於多個setState的優化,類似將 state 更新動作放到一個 queue 裡,最後算出更新的 值 才是真正拿去更新state ),React 不會在多個有意義的事件(例如點擊)之間進行批處理,每個點擊都會單獨處理。
請放心,React 只在通常情況下安全時才進行批處理。這確保了,例如,如果第一次按鈕點擊禁用了表單,第二次點擊不會再次提交它。
更新state後會再次觸發 render 導致元件更新,創造新的snapShot,當snapShot 與前次比較有差異,則會在commit階段實際更新有差異的 DOM。
感謝閱讀,如果有錯誤或是講得不清楚的部分,再請留言指教