愛伊米

你覺得 Hooks 這一點煩嗎?

作者:卡頌

大家好,我卡頌。

昨天一個小夥伴發了一個給我,讓我解釋下原因。

我一看,好傢伙,小小一個,知識點囊括了:

的閉包問題

是如何組裝的

相信看懂這個,對會有更深的認識。

讓人懵逼的Demo

包含一個按鈕、一個列表。

點選按鈕,呼叫方法,向列表中插入一項:

顯示效果:

你覺得 Hooks 這一點煩嗎?

燒腦的地方在於,呼叫方法插入的是一個點選後會呼叫 add 方法的按鈕:

點選按鈕7下後的顯示效果:

你覺得 Hooks 這一點煩嗎?

那麼問題來了,點選帶數字按鈕(會呼叫和點選一樣的方法)後會有什麼效果呢?

state的組裝和閉包問題

如果你認為會插入一個新按鈕:

那就錯了。

你覺得 Hooks 這一點煩嗎?

正確答案是:點選對應按鈕後長度變為按鈕對應數字 + 1,且最後一項的數字為點選前最大數字 + 1。

比如,點選前最大數字為6

你覺得 Hooks 這一點煩嗎?

如果點選 0,長度變為,且最後一項為:

你覺得 Hooks 這一點煩嗎?

如果點選 2,長度變為,且最後一項為:

你覺得 Hooks 這一點煩嗎?

這是兩個因素共同作用的結果:

的閉包問題

是如何組裝的

原因分析

再來看看方法:

點選後呼叫,所以會基於所屬上下文(函式)形成閉包,閉包中包括:

add

list

setList

你覺得 Hooks 這一點煩嗎?

屬於級作用域,不在該閉包內

其中與來自於呼叫後的返回值:

一種常見的認知誤區是:多次呼叫返回的是同一個引用。

事實上,每次呼叫返回的都是基於如下公式計算得出的:

基準state + update1 + update2 + 。。。 = 當前state

所以是一個全新的物件。

如果你想了解更多、計算的細節

參考:https://react。iamkasong。com/state/mental。html

當時:

元件首次

建立

依賴,形成閉包,閉包中的

接下來,點選:

呼叫方法,該方法來自於首屏渲染建立的閉包

方法中依賴的來自於同一個閉包,所以

依賴,形成閉包,閉包中的

所以,對於,

你覺得 Hooks 這一點煩嗎?

任何時候點選他實際上執行的都是:

那麼如何修復這個問題呢,也很簡單,將的引數改為函式形式:

函式引數中的來自於中儲存的,而不是閉包中的。

總結

由於總是在元件時才會計算新狀態,這為帶來比較重的心智負擔。

相比而言,採用細粒度更新實現的(比如的)可以實時更新狀態,操作起來更符合直覺。