<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你覺得Hooks這一點煩嗎?

          共 3922字,需瀏覽 8分鐘

           ·

          2021-09-29 08:54


          源 /         文/ 卡頌

          大家好,我卡頌。

          昨天一個小伙伴發(fā)了一個Demo給我,讓我解釋下原因。

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

          • Hooks的閉包問題

          • state是如何組裝的

          相信看完這個Demo,對函數(shù)組件會有更深的認識。

          讓人懵逼的Demo

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

           <div className="App">
              <button onClick={add}>Add</button>
              {list.map(val => val)}
            </div>

          點擊按鈕,調(diào)用add方法,向列表中插入一項:


          let i = 0;

          export default function App() {
            const [list, setList] = useState([]);

            const add = () => {
              // ...
            };

            return (
              <div className="App">
                <button onClick={add}>Add</button>
                {list.map(val => val)}
              </div>

            );
          }

          顯示效果:

          燒腦的地方在于,調(diào)用add方法插入的是一個「點擊后會調(diào)用 add 方法的按鈕」

          const add = () => {
              setList(
                list.concat(
                  <button 
                    key={i} 
                    onClick={add}>

                    {i++}
                  </button>

                )
              );
            };

          點擊Add按鈕7下后的顯示效果:

          那么問題來了,點擊帶數(shù)字按鈕(會調(diào)用和點擊Add按鈕一樣的add方法)后會有什么效果呢?

          state的組裝和閉包問題

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

          那就錯了。

          正確答案是:點擊對應(yīng)按鈕后list長度變?yōu)?strong style="color: rgb(145, 109, 213);">「按鈕對應(yīng)數(shù)字 + 1」,且最后一項的數(shù)字為「點擊前最大數(shù)字 + 1」。

          比如,點擊前最大數(shù)字為6

          如果點擊 0,list長度變?yōu)?/span>0 + 1 = 1,且最后一項為6 + 1 = 7

          如果點擊 2,list長度變?yōu)?/span>2 + 1 = 3,且最后一項為6 + 1 = 7

          這是兩個因素共同作用的結(jié)果:

          • Hooks的閉包問題

          • state是如何組裝的

          原因分析

          再來看看add方法:

          const add = () => {
              setList(
                list.concat(
                  <button 
                    key={i} 
                    onClick={add}>

                    {i++}
                  </button>

                )
              );
            };

          button點擊后調(diào)用add,所以會基于add所屬上下文(App函數(shù))形成閉包,閉包中包括:

          • add

          • list

          • setList

          i屬于module級作用域,不在該閉包內(nèi)

          其中listsetList來自于useState調(diào)用后的返回值:

          const [list, setList] = useState([]);

          一種常見的認知誤區(qū)是:多次調(diào)用useState返回的list是同一個引用。

          事實上,每次調(diào)用useState返回的list都是基于如下公式計算得出的:

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

          所以是一個全新的對象。

          如果你想了解更多update、state計算的細節(jié),參考React技術(shù)揭秘[1]

          首屏渲染時:

          1. App組件首次render

          2. 創(chuàng)建list = []

          3. <button onClick={add}>Add</button>依賴add,形成閉包,閉包中的list = []

          接下來,點擊Add按鈕

          1. 調(diào)用add方法,該方法來自于首屏渲染創(chuàng)建的閉包

          2. add方法中依賴的list來自于同一個閉包,所以list = []

          3. <button key={i} onClick={add}>{i++}</button>依賴add,形成閉包,閉包中的list = []

          所以,對于按鈕0,

          任何時候點擊他實際上執(zhí)行的都是:

          setList(
            [].concat(
              <button key={i} onClick={add}>{i++}</button>
            )
          );

          那么如何修復(fù)這個問題呢,也很簡單,將setList的參數(shù)改為函數(shù)形式:

          // 之前
          setList(list.concat(<button key={i} onClick={add}>{i++}</button>));
          // 之后
          setList(list => list.concat(<button key={i} onClick={add}>{i++}</button>));

          函數(shù)參數(shù)中的list來自于Hooks中保存的list,而不是閉包中的list。

          總結(jié)

          由于Hooks總是在組件render時才會計算新狀態(tài),這為Hooks帶來比較重的心智負擔。

          相比而言,采用「細粒度更新」實現(xiàn)的Hooks(比如VUEComposition API)可以實時更新狀態(tài),操作起來更符合直覺。

          在使用Hooks過程中,你有沒有遇到類似的頭疼問題呢?

          參考資料

          [1]

          React技術(shù)揭秘:https://react.iamkasong.com/state/mental.html#%E5%90%8C%E6%AD%A5%E6%9B%B4%E6%96%B0%E7%9A%84react


          推薦閱讀

          中國唯一一座沒有高樓大廈的新一線城市,也太佛了吧


          國內(nèi)有程序員電視劇了,結(jié)果看了一分鐘,就吐了...


          華為最美小姐姐被外派墨西哥后...




          END


          頂級程序員:topcoding

          做最好的程序員社區(qū):Java后端開發(fā)、Python、大數(shù)據(jù)、AI


          一鍵三連「分享」、「點贊」和「在看」


          瀏覽 24
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲国产毛片 | 五月丁香亭亭 | 久久久久久这里只有好吊视频 | 日本黄色性情视频 | 91久久久无码国产一区二区三区 |