如果将第二个参数作为数组传递并放入空对象,为什么 useEffect 会导致无限循环
Why useEffect makes infinitive loop if pass the second param as array and inside put empty object
我有 API 过滤器参数的对象,我传递给 useEffect 的这个对象。
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: {};
for (let key in props.route.params) {
if (props.route.params.hasOwnProperty(key)) {
dataForFilter[key] = props.route.params[key];
}
}
useEffect(() => {
async function fetchData() {
const body = {
...dataForFilter,
};
loadData(url, body);
}
fetchData();
}, [dataForFilter]);
默认情况下对象是空的,但是如果我将数组中的空对象作为第二个参数传递,这会造成无限循环。
我不明白为什么?请有人能解释一下为什么以及如何解决这个问题。
每次函数运行时,都会在此处创建一个新的空对象:
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: {};
因此,如果 defaultFormData[someKey]
不存在,则依赖项数组的值会在每次渲染时更改。空对象不等于自身。
console.log([{}] === [{}]);
console.log({} === {});
改为在函数外部创建对象,使其引用稳定。
const emptyObj = {};
const MyComponent = ({ defaultFormData }) => {
// ...
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: emptyObj;
在您的 useEffect 中,调用一个函数来重新渲染组件。在您的 useEffect 依赖项(末尾的数组)中,您传入了 dataForFilter 作为依赖项。这意味着,只要 dataForFilter 发生变化,就会再次调用 useEffect。但是由于 useEffect 使组件重新渲染,并且 dataForFilter 没有被定义为状态而是组件内部的普通变量,因此它将被重新定义为另一个值(注意:即使具有相同值的对象也不是与之前相同的对象)。如果您希望在组件呈现时调用任何 useEffect 一次,请传递一个空数组作为依赖项,如下所示:
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined' // <-- dataForFilter gets evaluated again and changes its value, which calls the useEffect
? defaultFormData[someKey]
: {};
for (let key in props.route.params) {
if (props.route.params.hasOwnProperty(key)) {
dataForFilter[key] = props.route.params[key];
}
}
useEffect(() => {
async function fetchData() {
const body = {
...dataForFilter,
};
loadData(url, body); // <-- You rerender the component somewhere in this function, dataForFilter gets defined again and is another object (with the same value BUT still another object)
}
fetchData();
}, []); // <-- Empty array as dependency, only gets called once
我有 API 过滤器参数的对象,我传递给 useEffect 的这个对象。
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: {};
for (let key in props.route.params) {
if (props.route.params.hasOwnProperty(key)) {
dataForFilter[key] = props.route.params[key];
}
}
useEffect(() => {
async function fetchData() {
const body = {
...dataForFilter,
};
loadData(url, body);
}
fetchData();
}, [dataForFilter]);
默认情况下对象是空的,但是如果我将数组中的空对象作为第二个参数传递,这会造成无限循环。 我不明白为什么?请有人能解释一下为什么以及如何解决这个问题。
每次函数运行时,都会在此处创建一个新的空对象:
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: {};
因此,如果 defaultFormData[someKey]
不存在,则依赖项数组的值会在每次渲染时更改。空对象不等于自身。
console.log([{}] === [{}]);
console.log({} === {});
改为在函数外部创建对象,使其引用稳定。
const emptyObj = {};
const MyComponent = ({ defaultFormData }) => {
// ...
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
? defaultFormData[someKey]
: emptyObj;
在您的 useEffect 中,调用一个函数来重新渲染组件。在您的 useEffect 依赖项(末尾的数组)中,您传入了 dataForFilter 作为依赖项。这意味着,只要 dataForFilter 发生变化,就会再次调用 useEffect。但是由于 useEffect 使组件重新渲染,并且 dataForFilter 没有被定义为状态而是组件内部的普通变量,因此它将被重新定义为另一个值(注意:即使具有相同值的对象也不是与之前相同的对象)。如果您希望在组件呈现时调用任何 useEffect 一次,请传递一个空数组作为依赖项,如下所示:
let dataForFilter = typeof defaultFormData[someKey] !== 'undefined' // <-- dataForFilter gets evaluated again and changes its value, which calls the useEffect
? defaultFormData[someKey]
: {};
for (let key in props.route.params) {
if (props.route.params.hasOwnProperty(key)) {
dataForFilter[key] = props.route.params[key];
}
}
useEffect(() => {
async function fetchData() {
const body = {
...dataForFilter,
};
loadData(url, body); // <-- You rerender the component somewhere in this function, dataForFilter gets defined again and is another object (with the same value BUT still another object)
}
fetchData();
}, []); // <-- Empty array as dependency, only gets called once