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

          React useEffect()你真的會(huì)用嗎?談?wù)勊臒o(wú)限循環(huán)是怎樣來(lái)的

          共 2164字,需瀏覽 5分鐘

           ·

          2021-12-20 11:26

          前言

          我們都知道useEffect()用來(lái)引入具有「副作用」的操作,例如AJAX請(qǐng)求DOM操作啟動(dòng)與結(jié)束倒計(jì)時(shí)監(jiān)聽與接觸事件等,這些都可以在useEffect鉤子去做。那么,是不是就真的那么簡(jiǎn)單的可以直接使用了呢?不是的,你可能會(huì)遇到一個(gè)陷阱,那就是組件渲染的無(wú)限循環(huán),本文將為各位同學(xué)詳細(xì)介紹無(wú)限循環(huán)的常見場(chǎng)景以及如何避免。

          副作用

          副作用指的是當(dāng)調(diào)用函數(shù)時(shí),除開返回函數(shù)值之外,還對(duì)主調(diào)用函數(shù)產(chǎn)生附加的影響。JS的部分內(nèi)置函數(shù)是有副作用的,例如:

          [1,2,3].pop();?//?執(zhí)行完pop函數(shù)后,原數(shù)據(jù)會(huì)少一個(gè)元素

          無(wú)限循環(huán)

          下面我們通過(guò)幾個(gè)例子來(lái)認(rèn)識(shí)下useEffect的不恰當(dāng)用法導(dǎo)致的無(wú)限循環(huán);

          缺失依賴

          import?React,?{?Fragment,?useState?}?from?'react';

          function?countChange()?{
          ?const?[value,?setValue]?=?useState('');
          ?const?[count,?setCount]?=?useState(0);
          ?useEffect(()?=>?{
          ??setCount(count?+?1);
          ?});
          ?return?(
          ??<Fragment>
          ???<input
          ????type="text"
          ????value={value}
          ????onChange={({?target?})?=>
          ?{
          ?????setValue(target.value);
          ????}}
          ???/>
          ???<div>count?is?{count}div>

          ??Fragment>
          ??);
          }

          上述例子中,「input」框輸入時(shí)會(huì)去更新value的值,這時(shí)候頁(yè)面會(huì)重新渲染,因?yàn)?strong style="color: rgb(145, 109, 213);">「useEffect」沒(méi)有依賴參數(shù),這個(gè)時(shí)候便會(huì)每次渲染都會(huì)執(zhí)行副作用回調(diào),每次回調(diào)都會(huì)更新count,于是又會(huì)執(zhí)行回調(diào);陷入了無(wú)限循環(huán)。

          這個(gè)時(shí)候,只需要給「useEffect」加上個(gè)依賴,只有value的值有更新的時(shí)候,才去執(zhí)行副作用回調(diào)。避免了無(wú)限循環(huán);依賴項(xiàng)為空數(shù)組時(shí),代表只在初次渲染是調(diào)用一次;

          useEffect(()?=>?{
          ?setCount(count?+?1);
          },?[value]);

          數(shù)組或?qū)ο笞鳛橐蕾?/p>

          「useEffect」只有當(dāng)依賴發(fā)生改變時(shí)才會(huì)去觸發(fā)回調(diào),而且是通過(guò)淺層對(duì)象比較是否發(fā)生改變;那如果用對(duì)象或者數(shù)據(jù)作為依賴會(huì)發(fā)生什么呢?

          import?React,?{?Fragment,?useState?}?from?'react';

          function?countChange()?{
          ?const?[value,?setValue]?=?useState('');
          ?const?[count,?setCount]?=?useState(0);
          ?const?dep?=?['dep'];
          ?const?obj?=?{
          ??name:?'pp',
          ?};
          ?//?使用數(shù)組作為依賴
          ?useEffect(()?=>?{
          ??setCount(count?+?1);
          ?},?[dep]);
          ?//?使用對(duì)象作為依賴
          ?useEffect(()?=>?{
          ??setCount(count?+?1);
          ?},?[obj]);
          ?return?(
          ??<Fragment>
          ???<input
          ????type="text"
          ????value={value}
          ????onChange={({?target?})?=>
          ?{
          ?????setValue(target.value);
          ????}}
          ???/>
          ???<div>count?is?{count}div>

          ??Fragment>
          ?);
          }

          由于淺層對(duì)比的關(guān)系,比較的結(jié)果總是false,無(wú)論是數(shù)組還是對(duì)象作為依賴,都會(huì)一次又一次的觸發(fā)回調(diào);導(dǎo)致出現(xiàn)無(wú)限循環(huán)。

          數(shù)組作為對(duì)象可以通過(guò)「useRef」解決,更改引用本身不會(huì)觸發(fā)組件重新渲染,相應(yīng)代碼改為:

          const?{?current:?dep?}?=?useRef(['dep']);

          useEffect(()?=>?{
          ?setCount(count?+?1);
          },?[dep]);

          對(duì)象作為對(duì)象可以通過(guò)「useMemo」解決,只有在依賴關(guān)系發(fā)生變化時(shí)才會(huì)重新計(jì)算記憶化的值。相應(yīng)代碼改為:

          const?obj?=?useMemo(()?=>?({
          ?name:?'pp',
          }),?[])

          useEffect(()?=>?{
          ?setCount(count?+?1);
          },?[obj]);

          函數(shù)作為依賴

          函數(shù)作為依賴項(xiàng)也是會(huì)導(dǎo)致無(wú)限循環(huán)的,這里不再貼代碼;我們可以通過(guò)「useCallback」來(lái)解決;「useCallback」返回一個(gè)memoized版本的回調(diào),只有在依賴關(guān)系改變時(shí)才會(huì)改變。

          const?func?=?useCallback(()?=>?{
          ?return?'1';
          },?[]);

          總結(jié)

          「useEffect」功能很強(qiáng)大,但是如果使用不當(dāng)便會(huì)出現(xiàn)難以想象的問(wèn)題,因此一定要正確使用「useEffect」。若useEffect的依賴數(shù)組的依賴值為ObjectArrayFunction等引用型數(shù)據(jù),那么就需注意了。

          結(jié)語(yǔ)

          「??關(guān)注+點(diǎn)贊+收藏+評(píng)論+轉(zhuǎn)發(fā)??」,原創(chuàng)不易,鼓勵(lì)筆者創(chuàng)作更多高質(zhì)量文章

          「關(guān)注公眾號(hào)IQ前端,一個(gè)專注于CSS/JS開發(fā)技巧的前端公眾號(hào),更多前端小干貨等著你喔」

          • 歡迎關(guān)注IQ前端,更多「CSS/JS開發(fā)技巧」只在公眾號(hào)推送



          瀏覽 100
          點(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>
                  天天插B 婷婷免费 | 国产情趣综合 | 91午夜福利视频 | 日本欧洲黄色免费看 | 操逼动漫免费观看 |