hooks中,useEffect無限調用問題產生的原因


前言:我在我的另一篇博客中有說道useEffect監聽對象或者數組時會導致useEffect無限執行,並給予了解決方案-useEffect無限調用問題 .后來我想從其產生根源去理解並解決這個問題.

 

原因:

錯誤代碼

 const [test, setTest] = useState({ name: '小明', age: '18' });
  const init = () => {
    setTest({ name: '小紅', age: '16' });
  };
  useEffect(() => {
    init();
    console.log('kkk', test);
  }, [test]);

以上代碼,如果執行,會發現useEffect會無限執行.

分析原因有以下幾個方面.

   1.引用數據類型的比較是地址,即"引用"來比較的.

   2.js每次創建對象都會產生一個新的地址.

簡單來說就是

console.log({}==={})  //false

 但是

let a = {}
let b = a
console.log(a===b) //true

 也就是說,問題出在這行代碼

 const init = () => {
    setTest({ name: '小紅', age: '16' });
  };

 這個{name:'小紅',age:'16'}其實每次都是一個新的對象,在useEffect中比較的時候,每次都會拿到一個新的引用,所以useEffect每次都會執行,每次執行又拿到一個新的test.於是就變成了無限執行了.

 

解決方案:

所以我們可以用以下方案去避免這個問題的產生.

1.固定"引用".

即我們只用一個引用

let b = { name: '小明', age: '18' };
let a = { name: '小紅', age: '16' };
const Test= () => {
  const [test, setTest] = useState(b || { name: '小明', age: '18' }); //useState的默認值並不會更新,所以不會產生新引用
  const init = () => {
    setTest(a); //a的值不會變
  };
  useEffect(() => {
    init();
    console.log('kkk', test);
  }, [test]);
}

 

2.固定"值"

即我們只要保證對象里面的屬性和值是一樣的就行

  const [test, setTest] = useState({ name: '小明', age: '18' });
  const init = () => {
    setTest({ name: '小紅', age: '16' });
  };
  useEffect(() => {
    init();
    console.log('kkk', test);
  }, [JSON.stringify(test)]); //只要對象里面的鍵和值是一樣的,JSON.stringify(test)的值就不會變

 應該還有其他方案,但大致方向就是這兩類.

因為hooks的特性會導致組件代碼重復執行,所以類似解構的默認值會重復給.假如使用的dva又不在models里面給默認值而是在hooks里給的話,監聽這個變量就可能出現這個問題

const { btn={}} = useSelector((state) => state.buttonList);//假如buttonList里面btn並沒有默認值,那這里監聽btn就會出現useEffect多次進入的問題

 

   


免責聲明!

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



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