<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>

          前端性能優(yōu)化 - React.memo 解決函數(shù)組件重復(fù)渲染

          共 2456字,需瀏覽 5分鐘

           ·

          2022-06-11 13:25

          關(guān)注并將「趣談前端」設(shè)為星標(biāo)

          定期推送技術(shù)干貨/優(yōu)秀開(kāi)源/技術(shù)思維

          使用 React Hooks 時(shí)函數(shù)組件應(yīng)用的比較多,當(dāng)遇到組件重復(fù)渲染問(wèn)題不像類組件可以使用生命周期函數(shù) shouldComponentUpdateextends React.PureComponent 解決重復(fù)渲染問(wèn)題。

          使用 React.memo() 前后效果對(duì)比

          例如,一個(gè)父組件 Home 中渲染了子組件 List,同時(shí) Home 組件還有一個(gè)計(jì)數(shù)器組件,每次點(diǎn)擊 count 都會(huì)加 1,遇到類似的場(chǎng)景就會(huì)出現(xiàn)子組件重復(fù)渲染問(wèn)題,這是因?yàn)?React 中當(dāng)父組件的一個(gè)狀態(tài)改變后,無(wú)論和子組件是否有關(guān),子組件都會(huì)受到影響進(jìn)行重新渲染,這也是 React 中默認(rèn)的一個(gè)行為。

          函數(shù)組件中的解決方案是使用 React.memo() 函數(shù),將需要優(yōu)化的函數(shù)組件傳入即可。

          import?React,?{?useEffect,?useState?}?from?"react";

          //?未使用 memo:const List =?({ dataList })?=>?{
          const?List?=?React.memo(({?dataList?})?=>?{
          ??console.log("List?渲染");

          ??return?(
          ????

          ??????{dataList.map((item)?=>?(
          ?????????{item.title}?</h2>
          ??????))}
          ????div>
          ??);
          });

          const?Home?=?()?=>?{
          ??const?[count,?setCount]?=?useState(0);
          ??const?[dataList,?setDataList]?=?useState([]);

          ??useEffect(()?=>?{
          ????const?list?=?[
          ??????{?title:?"React?性能優(yōu)化",?id:?1?},
          ??????{?title:?"Node.js?性能優(yōu)化",?id:?2?},
          ????];
          ????setDataList(list);
          ??},?[]);

          ??return?(
          ????

          ??????type="button"?onClick={()?=>?setCount(count?+?1)}>
          ????????count:?{count}
          ??????</button>
          ??????>
          ????</div>
          ??);
          };

          export?default?Home;

          下圖對(duì)比了使用 React.memo() 前后的效果。

          image.png

          自定義控制對(duì)比過(guò)程

          函數(shù)React.memo() 還提供了第二個(gè)參數(shù) propsAreEqual,用來(lái)自定義控制對(duì)比過(guò)程。

          //?React.memo()?的?TypeScript?類型描述
          function?memo<T?extends?ComponentType<any>>(
          ??Component:?T,
          ??propsAreEqual?:?(
          ????prevProps:?Readonly>,
          ????nextProps:?Readonly>
          ??)?=>?boolean
          ):?MemoExoticComponent<T>
          ;

          React.memo 無(wú)效情況

          一是 React.memo 對(duì)普通的引用類型是無(wú)效的。例如,在 List 組件增加 user 屬性,即使使用了 React.memo() ,每次點(diǎn)擊 count, List 組件還會(huì)重復(fù)渲染。

          const?Home?=?()?=>?{
          ??const?user?=?{name:?'哈哈'};
          ??...

          ??return?(
          ????<div>
          ??????<List?dataList={dataList}?user={user}?/>
          ????div>

          ??);
          };

          與 React.memo() 結(jié)合使用時(shí),普通引用類型對(duì)象需要通過(guò) useMemo、useState 處理,來(lái)避免組件的重復(fù)渲染。

          const?user?=?useMemo(()?=>?({?name:?"哈哈"?}),?[]);
          const?[user]?=?useState({?name:?"哈哈"?});

          還有一種情況是函數(shù)組中包括了一些 Hooks 例如 useState、useContext,當(dāng)上下文發(fā)生變化時(shí),組件也同樣會(huì)重新渲染,React.memo 在這里僅比較 props。上面例子中,如果把 button 組件放到 List 組件里,每次點(diǎn)擊,List 也還是會(huì)被重新渲染。

          const?List?=?React.memo(({?dataList?})?=>?{
          ??console.log("List?渲染");
          ??const?[count,?setCount]?=?useState(0);

          ??return?(
          ????<div>
          ??????<button?type="button"?onClick={()?=>?setCount(count?+?1)}>
          ????????List?count:?{count}
          ??????button>

          ??????{dataList.map((item)?=>?(
          ????????<h2?key={item.id}>?{item.title}?h2>
          ??????))}
          ????div>
          ??);
          });

          總結(jié)

          React.memo() 是一個(gè)高階組件,接收一個(gè)組件并返回一個(gè)新組件。它會(huì)記憶組件上次的 Props,同下次需要更新的 Props 做 “淺對(duì)比”,如果相同就不做更新,只有在不同時(shí)才會(huì)重新渲染。如果你的組件存在一些耗時(shí)的計(jì)算,每次重新渲染對(duì)頁(yè)面性能顯然是糟糕的,這時(shí) React.memo() 對(duì)你來(lái)說(shuō)也許是一個(gè)好的選擇。并不是所有的組件都要引入 React.memo(),自身淺對(duì)比這個(gè)過(guò)程也會(huì)有一些消耗,如果沒(méi)有特殊需求,也不一定非要使用。

          ?? 看完三件事

          如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:

          • 點(diǎn)個(gè)【在看】,或者分享轉(zhuǎn)發(fā),讓更多的人也能看到這篇內(nèi)容
          • 關(guān)注公眾號(hào)【趣談前端】,定期分享?工程化?/?可視化?/?低代碼?/?優(yōu)秀開(kāi)源。





          從零搭建全??梢暬笃林谱髌脚_(tái)V6.Dooring

          從零設(shè)計(jì)可視化大屏搭建引擎

          Dooring可視化搭建平臺(tái)數(shù)據(jù)源設(shè)計(jì)剖析

          可視化搭建的一些思考和實(shí)踐

          基于Koa + React + TS從零開(kāi)發(fā)全棧文檔編輯器(進(jìn)階實(shí)戰(zhàn)




          點(diǎn)個(gè)在看你最好看


          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  亚洲精品人妻系列 | 免费成人18禁 | 午夜成人黄片 | 欧美成人性爱诱惑 | 中文字幕手机在线视频 |