[英]Why this react hook cause infinite loop?
This piece of code will run infinitely, but no matter removing the useValue(object)
or useTest()
will stop the infinite run.这段代码会无限运行,但是不管去掉useValue(object)
还是useTest()
都会停止无限运行。 This whole thing does not make sense to me, can somebody explain it?这整件事对我来说没有意义,有人可以解释一下吗?
https://codesandbox.io/s/zen-currying-v2zu1?file=/src/App.jshttps://codesandbox.io/s/zen-currying-v2zu1?file=/src/App.js
import React from "react";
import { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
// this code can also stop the infinite loop
// const [object] = useState({
// name: "",
// personId: ""
// });
const object = {
name: "",
personId: ""
};
// strange thing: remove useValue or useTest can stop the ifinite loop
useValue(object);
useTest();
// this console will run infinitely
console.log(object);
return <div className="App">{"123"}</div>;
}
export const useTest = () => {
const [a, setA] = useState(1);
useEffect(() => {
setA(2);
}, []);
};
const useValue = (value) => {
const [a, setA] = useState(value);
useEffect(() => {
setA(value);
}, [value]);
// return a
};
Make sure to memoize your object in order to properly use it in dependencies.确保记住您的 object 以便在依赖项中正确使用它。
const { useMemo } from 'react';
const object = useMemo(
() => ({
name: "",
personId: ""
}),
[]
);
The reason behind the infinite loop is because you're providing a non-memoized object into your dependency array in useEffect
.无限循环背后的原因是因为您在 useEffect 的依赖数组中提供了一个非记忆的useEffect
。
Object comparison in Javascript is more complex than just comparing obj1 === obj2
, as there is a reference that needs to be taken into account. Javascript 中的 Object 比较比仅比较obj1 === obj2
更复杂,因为需要考虑一个参考。
Read more about comparing objects in javascript here在此处阅读有关比较 javascript 中的对象的更多信息
Because object
is a reference type, its identity will change every time you rerender App
.因为object
是引用类型,所以每次重新渲染App
时它的标识都会改变。 There you use a custom hook useValue
and pass object
into it.在那里,您使用自定义挂钩useValue
并将object
传递给它。 Since you also register it as value
in the dependency array of useEffect
, useEffect
will be triggered, setting a new state, ending in rerendering and looping.由于您还在useEffect
的依赖数组中将其注册为value
,因此将触发useEffect
,设置新的 state,以重新渲染和循环结束。
Because you passed an object in the dependencies.因为您在依赖项中传递了 object。 useEffect with do a shallow comparison so it always renders. useEffect with 做一个浅比较,所以它总是呈现。
There are some solutions.有一些解决方案。 Read here . 在这里阅读。 You could modify your useValue hook to use JSON.stringify as below.您可以修改您的 useValue 挂钩以使用 JSON.stringify,如下所示。
const useValue = (value) => {
const [a, setA] = useState(value);
useEffect(() => {
setA(value);
}, [JSON.stringify(value)]);
// return a
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.