所以,我偶然發現了這種奇怪的情況:
我有一個全域 React Context 提供程式,提供全域狀態,就像這樣
const Context = createContext();
const ContextProvider = ({children}) => {
const [state, setState] = useState('');
return <Context.Provider value={{state, setState}}>{children}</Context.Provider>
}
const useMyState = () => {
const {state, setState} = useContext(Context);
return {
state,
setState
}
}
const Component = () => {
const {setState} = useMyState();
useEffect(() => {
elementRef.addEventListener('click', () => {
setState('someState');
});
return () => {
elementRef.removeEventListener('click', () => null);
}
},[])
return <>
// ...
</>
}
eslint建議將 mysetState添加到useEffect的依賴陣列中,
useEffect(() => {
elementRef.addEventListener('click', () => {
setState('someState');
});
},[setState])
我猜這可能與useMyState.ts檔案內背景關系的解構有關
但這感覺有點奇怪和不直觀......
我的問題是setState依賴陣列中真的需要嗎?如果是這樣,為什么?
uj5u.com熱心網友回復:
我的問題是
setState依賴陣列中真的需要嗎?
不,它不是,但 ESLint 不知道,因為它無法知道setState你正在使用的背景關系物件的成員是穩定的。你知道這一點(因為 setter 被 保證是穩定的useState,并且你通過背景關系和你的useMyState鉤子逐字傳遞它),但 ESLint 不知道這一點。
您可以將其添加為依賴項以使 ESLint 滿意(如果您已經提供了一個陣列,它不會有任何區別,因為 setter 永遠不會改變;如果您不提供陣列,請參見下文),或者您可以將在評論中告訴 ESLint 跳過檢查該代碼,或者您可以關閉規則(但是很容易錯過依賴項,所以如果這樣做要小心)。
(如果您沒有提供陣列 [因為您希望效果在每次渲染后運行],添加一個帶有 setter 的陣列將阻止這種情況發生,因此您需要選擇禁用 ESLint這種情況下的錯誤。或者有一些討厭的解決方案,比如使用一個帶有不斷增加的數值的 ref。:-) )
但是,該代碼存在問題。它不斷地向元素添加新的事件偵聽器而不洗掉它們,因為沒有依賴陣列,useEffect每次組件呈現時都會呼叫回呼,并且每次都創建一個新的事件處理函式,所以它們會堆疊起來。
所以你需要建立elementRef.current一個依賴,你需要一個清理回呼:
const Component = () => {
const {setState} = useMyState();
useEffect(() => {
const handler = () => {
setState("someState");
};
const element = elementRef.current;
// Note ??????????????????^^^^^^^^
element.addEventListener("click", handler);
return () => {
element.removeEventListener("click", handler);
};
}, [elementRef.current]); // <== Optionally add `setState` to this
return <>
// ...
</>;
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/459142.html
標籤:javascript 反应 反应钩子 关闭
上一篇:動態多變數濾波函式
