[英]useEffect causing infinite looping with constant dependency
useEffect
is getting triggered even though the dependency array has constant object.即使依赖数组具有常量 object,
useEffect
也会被触发。
I tried extracting the logic and put the object in useState
我尝试提取逻辑并将 object 置于
useState
const payload = {
limit: 5,
offset: 0,
filterBy: 'All',
};
useEffect(() => {
const defaultPayload = {
limit: 10,
offset: 0,
filterBy: 'All',
};
dispatch({ type: RANDOM_CONST, payload: payload || defaultPayload });
}, [dispatch, payload]);
It should trigger only when payload
changes.它应该仅在
payload
更改时触发。 Since, payload
is a constant, it should just run once and note infinite times.由于
payload
是一个常数,它应该只运行一次并注意无限次。
There are two problems that may cause the re-render, notice that the useEffect
makes a shallow comparison with the dep-array
values:有两个问题可能会导致重新渲染,请注意
useEffect
与dep-array
值进行了浅比较:
payload
is a new object on every render, therefore oldPayload === payload
always false
, causes the useEffect
to run. payload
在每次渲染时都是一个新的 object,因此oldPayload === payload
总是false
,导致useEffect
运行。
If dispatch
comes from 3rd party library (like react-redux hook ), it might be making a new dispatch
reference on every render, therefore again oldDispatch === dispatch
is aways false
and causes useEffect
to run.如果
dispatch
来自 3rd 方库(如react-redux 挂钩),它可能会在每个渲染上创建一个新的dispatch
引用,因此oldDispatch === dispatch
再次为false
并导致useEffect
运行。
To fix it, you can move the "constant object" to the outer scope (which will run once), and use useCallback
hook if you passing the dispatch
.要修复它,您可以将“常量对象”移动到外部 scope (它将运行一次),并在传递
dispatch
时使用useCallback
钩子。
Example from
react-redux
docs: When passing a callback using dispatch to a child component, it is recommended to memoize it withuseCallback
, since otherwise child components may render unnecessarily due to the changed reference.来自
react-redux
文档的示例:当使用 dispatch 向子组件传递回调时,建议使用useCallback
来记忆它,否则子组件可能会由于引用的更改而不必要地呈现。
const payload = {
limit: 5,
offset: 0,
filterBy: 'All'
};
const App = () => {
// v Memoize it if passing as a callback,
// check in library docs if there is a new instance
// on every render
const dispatch = useDispatch();
useEffect(() => {
dispatch({ type: RANDOM_CONST, payload });
}, []);
return;
};
Note: There is no indication in question where the
dispatch
function comes from.注意:没有迹象表明
dispatch
function 来自何处。
You can convert the objects to JSON strings and compare them inside your useEffect hook:您可以将对象转换为 JSON 字符串并在您的 useEffect 挂钩中进行比较:
JSON.stringify(oldValue) === JSON.stringify(newValue) // true
Note that object keys should have the same order:请注意,object 密钥应具有相同的顺序:
JSON.stringify({a: 1, b: 2}) === JSON.stringify({a: 1, b: 2}) // true
JSON.stringify({a: 1, b: 2}) === JSON.stringify({b: 2, a: 1}) // false
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.