前言:我在我的另一篇博客中有說道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多次進入的問題
