[英]How to handle an unchanging array in useEffect dependency array?
我有一個這樣的組件。 我想要的是 useEffect 函數在myBoolean
更改時隨時運行。
我可以通過將依賴數組設置為[myBoolean]
來實現這一點。 但是后來我收到一條警告,指出我違反了exhaustive-deps
規則,因為我在函數內部引用了myArray
。 我不想違反該規則,因此我將依賴項數組設置為[myBoolean, myArray]
。
但后來我得到了一個無限循環。 發生的事情是每次myArray
更改時都會觸發 useEffect ,這是每次更改,因為事實證明myArray
來自 redux 並在每次重新渲染時重新生成。 即使數組的元素與之前的相同,React 也會使用===
將數組與其之前的版本進行比較,並且它不是同一個對象,因此不相等。
那么這樣做的正確方法是什么? 如何僅在myBoolean
更改時運行我的代碼,而不違反exhaustive-deps
規則?
我已經看到了這個,但我仍然不確定在這種情況下的解決方案是什么。
const MyComponent = ({ myBoolean, myArray }) => {
const [myString, setMyString] = useState('');
useEffect(() => {
if(myBoolean) {
setMyString(myArray[0]);
}
}, [myBoolean, myArray]
}
解決方案1
如果您總是需要第 1 項,請從數組中提取它,並將其用作依賴項:
const MyComponent = ({ myBoolean, myArray }) => {
const [myString, setMyString] = useState('');
const item = myArray[0];
useEffect(() => {
if(myBoolean) {
setMyString(item);
}
}, [myBoolean, item]);
}
解決方案2
如果您不想對myArray
更改做出反應,請使用useRef()
將其設置為 ref :
const MyComponent = ({ myBoolean, myArray }) => {
const [myString, setMyString] = useState('');
const arr = useRef(myArray);
useEffect(() => { arr.current = myArray; }, [myArray]);
useEffect(() => {
if(myBoolean) {
setMyString(arr.current);
}
}, [myBoolean]);
}
注意: redux 不應該在每次狀態更新時生成一個新數組,除非數組或它的項目實際上發生了變化。 如果選擇器生成數組,請閱讀有關記憶化選擇器的信息( reselect是一個很好的庫)。
我有一個關於保存previous props
的想法。 然后我們將在稍后實現功能比較previous props
。 比較值將用於決定處理useEffect
中no dependency
函數更改。
它將占用更多的計算和內存。 只是一個想法。
這是我的例子:
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
function arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => val === b[index]);
}
const MyComponent = ({ myBoolean, myArray }) => {
const [myString, setMyString] = useState('');
const previousArray = usePrevious(myArray);
const previousBoolean = usePrevious(myBoolean);
const handleEffect = () => {
console.log('child-useEffect-call-with custom compare');
if(myBoolean) {
setMyString(myArray[0]);
}
};
//handle effect in custom solve
useEffect(() => {
//check change here
const isEqual = arrayEquals(myArray, previousArray) && previousBoolean === myBoolean;
if (!isEqual)
handleEffect();
});
useEffect(() => {
console.log('child-useEffect-call with sallow compare');
if(myBoolean) {
setMyString(myArray[0]);
}
}, [myBoolean, myArray]);
return myString;
}
const Any = () => {
const [array, setArray] = useState(['1','2','3']);
console.log('parent-render');
//array is always changed
// useEffect(() => {
// setInterval(() => {
// setArray(['1','2', Math.random()]);
// }, 2000);
// }, []);
//be fine. ref is not changed.
// useEffect(() => {
// setInterval(() => {
// setArray(array);
// }, 2000);
// }, []);
//changed ref but value in array are not changed -> handle this case
useEffect(() => {
setInterval(() => {
setArray(['1','2', '3']);
}, 2000);
}, []);
return <div> <MyComponent myBoolean={true} myArray={array}/> </div>;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.