作者:卡頌
大家好,我卡頌。
昨天一個小夥伴發了一個給我,讓我解釋下原因。
我一看,好傢伙,小小一個,知識點囊括了:
的閉包問題
是如何組裝的
相信看懂這個,對會有更深的認識。
讓人懵逼的Demo
包含一個按鈕、一個列表。
點選按鈕,呼叫方法,向列表中插入一項:
顯示效果:
燒腦的地方在於,呼叫方法插入的是一個點選後會呼叫 add 方法的按鈕:
點選按鈕7下後的顯示效果:
那麼問題來了,點選帶數字按鈕(會呼叫和點選一樣的方法)後會有什麼效果呢?
state的組裝和閉包問題
如果你認為會插入一個新按鈕:
那就錯了。
正確答案是:點選對應按鈕後長度變為按鈕對應數字 + 1,且最後一項的數字為點選前最大數字 + 1。
比如,點選前最大數字為6
如果點選 0,長度變為,且最後一項為:
如果點選 2,長度變為,且最後一項為:
這是兩個因素共同作用的結果:
的閉包問題
是如何組裝的
原因分析
再來看看方法:
點選後呼叫,所以會基於所屬上下文(函式)形成閉包,閉包中包括:
add
list
setList
屬於級作用域,不在該閉包內
其中與來自於呼叫後的返回值:
一種常見的認知誤區是:多次呼叫返回的是同一個引用。
事實上,每次呼叫返回的都是基於如下公式計算得出的:
基準state + update1 + update2 + 。。。 = 當前state
所以是一個全新的物件。
如果你想了解更多、計算的細節
參考:https://react。iamkasong。com/state/mental。html
當時:
元件首次
建立
依賴,形成閉包,閉包中的
接下來,點選:
呼叫方法,該方法來自於首屏渲染建立的閉包
方法中依賴的來自於同一個閉包,所以
依賴,形成閉包,閉包中的
所以,對於,
任何時候點選他實際上執行的都是:
那麼如何修復這個問題呢,也很簡單,將的引數改為函式形式:
函式引數中的來自於中儲存的,而不是閉包中的。
總結
由於總是在元件時才會計算新狀態,這為帶來比較重的心智負擔。
相比而言,採用細粒度更新實現的(比如的)可以實時更新狀態,操作起來更符合直覺。