日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何解決React.useEffect()的無限循環(huán)

useEffect() 主要用來管理副作用,比如通過網(wǎng)絡(luò)抓取、直接操作 DOM、啟動和結(jié)束計時器。

十年的新建網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整新建建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“新建網(wǎng)站設(shè)計”,“新建網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

雖然useEffect() 和 useState(管理狀態(tài)的方法)是最常用的鉤子之一,但需要一些時間來熟悉和正確使用。

使用useEffect()時,你可能會遇到一個陷阱,那就是組件渲染的無限循環(huán)。在這篇文章中,會講一下產(chǎn)生無限循環(huán)的常見場景以及如何避免它們。

1. 無限循環(huán)和副作用更新狀態(tài)

假設(shè)我們有一個功能組件,該組件里面有一個 input 元素,組件是功能是計算 input 更改的次數(shù)。

我們給這個組件取名為 CountInputChanges,大概的內(nèi)容如下:

 
 
 
 
  1. function CountInputChanges() {
  2.   const [value, setValue] = useState('');
  3.   const [count, setCount] = useState(-1);
  4.  useEffect(() => setCount(count + 1));
  5.   const onChange = ({ target }) => setValue(target.value);
  6.   return (
  7.     
  8.  
  9.  
    Number of changes: {count}
  10.  
  •   )
  • }
  •   是受控組件。value變量保存著 input 輸入的值,當(dāng)用戶輸入輸入時,onChange事件處理程序更新 value 狀態(tài)。

    這里使用useEffect()更新count變量。每次由于用戶輸入而導(dǎo)致組件重新渲染時,useEffect(() => setCount(count + 1))就會更新計數(shù)器。

    因為useEffect(() => setCount(count + 1))是在沒有依賴參數(shù)的情況下使用的,所以()=> setCount(count + 1)會在每次渲染組件后執(zhí)行回調(diào)。

    你覺得這樣寫會有問題嗎?

    運行了會發(fā)現(xiàn)count狀態(tài)變量不受控制地增加,即使沒有在input中輸入任何東西,這是一個無限循環(huán)。

    問題在于useEffect()的使用方式:

     
     
     
     
    1. useEffect(() => setCount(count + 1));

    它生成一個無限循環(huán)的組件重新渲染。

    在初始渲染之后,useEffect()執(zhí)行更新狀態(tài)的副作用回調(diào)函數(shù)。狀態(tài)更新觸發(fā)重新渲染。重新渲染之后,useEffect()執(zhí)行副作用回調(diào)并再次更新狀態(tài),這將再次觸發(fā)重新渲染。

    1.1通過依賴來解決

    無限循環(huán)可以通過正確管理useEffect(callback, dependencies)依賴項參數(shù)來修復(fù)。

    因為我們希望count在值更改時增加,所以可以簡單地將value作為副作用的依賴項。

     
     
     
     
    1. import { useEffect, useState } from 'react';
    2. function CountInputChanges() {
    3.   const [value, setValue] = useState('');
    4.   const [count, setCount] = useState(-1);
    5.  useEffect(() => setCount(count + 1), [value]);
    6.   const onChange = ({ target }) => setValue(target.value);
    7.   return (
    8.     
    9.  
    10.  
      Number of changes: {count}
    11.  
  •   );
  • }
  •  添加[value]作為useEffect的依賴,這樣只有當(dāng)[value]發(fā)生變化時,計數(shù)狀態(tài)變量才會更新。這樣做可以解決無限循環(huán)。

    1.2 使用 ref

    除了依賴,我們還可以通過 useRef() 來解決這個問題。

    其思想是更新 Ref 不會觸發(fā)組件的重新渲染。

     
     
     
     
    1. import { useEffect, useState, useRef } from "react";
    2. function CountInputChanges() {
    3.   const [value, setValue] = useState("");
    4.   const countRef = useRef(0);
    5.  useEffect(() => countRef.current++);
    6.   const onChange = ({ target }) => setValue(target.value);
    7.   return (
    8.     
    9.  
    10.  
      Number of changes: {countRef.current}
    11.  
  •   );
  • }
  •  useEffect(() => countRef.current++) 每次由于value的變化而重新渲染后,countRef.current++就會返回。引用更改本身不會觸發(fā)組件重新渲染。

    2. 無限循環(huán)和新對象引用

    即使正確設(shè)置了useEffect()依賴關(guān)系,使用對象作為依賴關(guān)系時也要小心。

    例如,下面的組件CountSecrets監(jiān)聽用戶在input中輸入的單詞,一旦用戶輸入特殊單詞'secret',統(tǒng)計 'secret' 的次數(shù)就會加 1。

     
     
     
     
    1. import { useEffect, useState } from "react";
    2. function CountSecrets() {
    3.   const [secret, setSecret] = useState({ value: "", countSecrets: 0 });
    4.   useEffect(() => {
    5.     if (secret.value === 'secret') {
    6.  setSecret(s => ({...s, countSecrets: s.countSecrets + 1}));    }
    7.  }, [secret]);
    8.   const onChange = ({ target }) => {
    9.     setSecret(s => ({ ...s, value: target.value }));
    10.   };
    11.   return (
    12.     
    13.  
    14.  
      Number of secrets: {secret.countSecrets}
    15.  
  •   );
  • }
  • 這是一個無限循環(huán)問題。

    為什么會這樣?

    secret對象被用作useEffect(..., [secret])。在副作用回調(diào)函數(shù)中,只要輸入值等于secret,就會調(diào)用更新函數(shù)

     
     
     
     
    1. setSecret(s => ({...s, countSecrets: s.countSecrets + 1}));

    這會增加countSecrets的值,但也會創(chuàng)建一個新對象。

    secret現(xiàn)在是一個新對象,依賴關(guān)系也發(fā)生了變化。所以useEffect(..., [secret])再次調(diào)用更新狀態(tài)和再次創(chuàng)建新的secret對象的副作用,以此類推。

    JavaScript 中的兩個對象只有在引用完全相同的對象時才相等。

    2.1 避免將對象作為依賴項

    解決由循環(huán)創(chuàng)建新對象而產(chǎn)生的無限循環(huán)問題的最好方法是避免在useEffect()的dependencies參數(shù)中使用對象引用。

     
     
     
     
    1. let count = 0;
    2. useEffect(() => {
    3.   // some logic
    4. }, [count]); // Good!

     
     
     
     
    1. let myObject = {
    2.   prop: 'Value'
    3. };
    4. useEffect(() => {
    5.   // some logic
    6. }, [myObject]); // Not good!
    7. useEffect(() => {
    8.   // some logic
    9. }, [myObject.prop]); // Good!

    修復(fù) 組件的無限循環(huán)問題,可以將useEffect(..., [secret])) 變?yōu)?useEffect(..., [secret.value])。

    僅在secret.value更改時調(diào)用副作用回調(diào)就足夠了,下面是修復(fù)后的代碼:

     
     
     
     
    1. import { useEffect, useState } from "react";
    2. function CountSecrets() {
    3.   const [secret, setSecret] = useState({ value: "", countSecrets: 0 });
    4.   useEffect(() => {
    5.     if (secret.value === 'secret') {
    6.       setSecret(s => ({...s, countSecrets: s.countSecrets + 1}));
    7.     }
    8.  }, [secret.value]);
    9.   const onChange = ({ target }) => {
    10.     setSecret(s => ({ ...s, value: target.value }));
    11.   };
    12.   return (
    13.     
    14.  
    15.  
      Number of secrets: {secret.countSecrets}
    16.  
  •   );
  • }
  •  3 總結(jié)

    useEffect(callback, deps)是在組件渲染后執(zhí)行callback(副作用)的 Hook。如果不注意副作用的作用,可能會觸發(fā)組件渲染的無限循環(huán)。

    生成無限循環(huán)的常見情況是在副作用中更新狀態(tài),沒有指定任何依賴參數(shù)

     
     
     
     
    1. useEffect(() => {
    2.   // Infinite loop!
    3.   setState(count + 1);
    4. });

    避免無限循環(huán)的一種有效方法是正確設(shè)置依賴項:

     
     
     
     
    1. useEffect(() => {
    2.   // No infinite loop
    3.   setState(count + 1);
    4. }, [whenToUpdateValue]);

    另外,也可以使用 Ref,更新 Ref 不會觸發(fā)重新渲染:

     
     
     
     
    1. useEffect(() => {
    2.   // No infinite loop
    3.   countRef.current++;
    4. });

    無限循環(huán)的另一種常見方法是使用對象作為useEffect()的依賴項,并在副作用中更新該對象(有效地創(chuàng)建一個新對象)

     
     
     
     
    1. useEffect(() => {
    2.   // Infinite loop!
    3.   setObject({
    4.     ...object,
    5.     prop: 'newValue'
    6.   })
    7. }, [object]);

    避免使用對象作為依賴項,只使用特定的屬性(最終結(jié)果應(yīng)該是一個原始值):

     
     
     
     
    1. useEffect(() => {
    2.   // No infinite loop
    3.   setObject({
    4.     ...object,
    5.     prop: 'newValue'
    6.   })
    7. }, [object.whenToUpdateProp]);

    當(dāng)使用useEffect()時,你還知道有其它方式會引起無限循環(huán)陷阱嗎?

    ~完,我是小智,我們下期見~


    新聞名稱:如何解決React.useEffect()的無限循環(huán)
    標(biāo)題來源:http://www.5511xx.com/article/dhjoiej.html