[react] 從useEffect中死循環理解useEffect 和useCallback的使用


原文參考地址

原文闡述了在useEffect中如果依賴為一個一直變化着的狀態時,它將陷入一個死循環。而在我的實驗中,發現如果setTest設置的不是一個常量值時,就會出現警告,提示需要將init函數也加入useEffect的依賴中。

import { useEffect, useState } from "react";

export default function InfiniteLoopUseEffect() {
  const [test, setTest] = useState(1);
  const init = () => {
    // setTest(2);
    setTest(test + 1);
  };
  useEffect(() => {
    init();
    console.log("kkk", test);
  }, [test]);

  return null;
}

image
這也是可以理解的,如果是setTest為一個常量,那么整個函數就是一個純函數,不依賴任何外物變化,正正當當的一個不可變量。

緊接着,我就按照提示加上了init依賴,不可避免,加了init,仍舊無法避免死循環的結果。
image
此時,終端又出現了警告,init函數每次都會隨着render變化,本身init函數就用了能刺激render變化的東西。可以嘗試,把它放在useEffect或者useCallback中。
放在useEffect中,沒什么用處,useEffect依賴的東西,時時刻刻都在變化,放在useCallback中可以試試。事實上,如果為”setTest(2)“,如果useEffect的依賴中加入了init函數,反而還會出現這個警告,可能本身當依賴中出現函數,就容易觸發這個警告。

一開始,我並沒有想過給useCallback加入依賴,就這樣,神奇的事發生了,無限循環就這也終止了!停在test為2的時候。

仔細分析useCallback的作用,將useCallback函數緩存到內存中,保持不變,只有當依賴變化時,useCallback才會更新。此時,是沒有依賴的,那就說明,useCallback中的東西都不會變化,即使是狀態test,它算是比較特別的了,也是不能變化的。所以,init的函數只加載了一次,其中的test一直是原來的那個test=1,所以,每次執行時,新的test依然還會是2。這又回到了“setTest(2)”的情況。

==================================================================

當把2換成對象或者是數組時(數組是一種特殊的對象,key=0,1,2,3...),還是會無限循環,因為每次新建的對象,都是不同的對象。
image

對象存放在堆內存中,獲取的對象實際上的內容是對象所在地址,由於每次對象都是new出來的所以這個地址值是不同的。對象引用與地址值的對應關系,是存放在棧內存中。字面量的數字或字符串,直接就是一個引用和它的內容,對比內容,自然都是相等的。
image
image
可以預見,對比依賴變化,采用的方式是通過”==“進行比較的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM