React useEffect - 在依赖数组中传递一个函数
React useEffect - passing a function in the dependency array
当我将函数表达式传递到 useEffect 依赖数组时,为什么会创建一个无限循环?函数表达式不会改变组件状态,它只会引用它。
// component has one prop called => sections
const markup = (count) => {
const stringCountCorrection = count + 1;
return (
// Some markup that references the sections prop
);
};
// Creates infinite loop
useEffect(() => {
if (sections.length) {
const sectionsWithMarkup = sections.map((section, index)=> markup(index));
setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
} else {
setSectionBlocks(blocks => []);
}
}, [sections, markup]);
如果标记改变了状态,我可以理解为什么它会创建一个无限循环,但它不会简单地引用 sections prop。
致那些正在寻找此问题解决方案的人
const markup = useCallback((count) => {
const stringCountCorrection = count + 1;
return (
// some markup referencing the sections prop
);
// useCallback dependency array
}, [sections]);
所以我不是在寻找与此问题相关的代码答案。如果可能的话,我正在寻找关于为什么会发生这种情况的详细解释。
我对原因更感兴趣,然后只是简单地找到解决问题的答案或正确方法。
为什么在 useEffect 依赖数组中传递一个在 useEffect 之外声明的函数会导致重新渲染,而状态和道具在所述函数中都没有改变。
问题是在每个渲染周期中,markup
都会被重新定义。 React 使用浅层对象比较来确定值是否更新。每个渲染周期 markup
都有不同的参考。您可以使用 useCallback
来记住该函数,这样引用就稳定了。您是否为 linter 启用了 react hook rules?如果你这样做了,它可能会标记它,告诉你原因,并提出这个建议来解决参考问题。
const markup = useCallback(
(count) => {
const stringCountCorrection = count + 1;
return (
// Some markup that references the sections prop
);
},
[count, /* and any other dependencies the react linter suggests */]
);
// No infinite looping, markup reference is stable/memoized
useEffect(() => {
if (sections.length) {
const sectionsWithMarkup = sections.map((section, index)=> markup(index));
setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
} else {
setSectionBlocks(blocks => []);
}
}, [sections, markup]);
Why is an infinite loop created when I pass a function expression
“无限循环”是组件一遍又一遍地重新渲染,因为 markup
函数是一个新的函数引用(内存中的指针),每次组件渲染并且 useEffect
触发重新渲染,因为它是一个依赖项。
解决方案正如@drew-reese 指出的那样,使用 useCallback
钩子来定义您的 markup
函数。
当我将函数表达式传递到 useEffect 依赖数组时,为什么会创建一个无限循环?函数表达式不会改变组件状态,它只会引用它。
// component has one prop called => sections
const markup = (count) => {
const stringCountCorrection = count + 1;
return (
// Some markup that references the sections prop
);
};
// Creates infinite loop
useEffect(() => {
if (sections.length) {
const sectionsWithMarkup = sections.map((section, index)=> markup(index));
setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
} else {
setSectionBlocks(blocks => []);
}
}, [sections, markup]);
如果标记改变了状态,我可以理解为什么它会创建一个无限循环,但它不会简单地引用 sections prop。
致那些正在寻找此问题解决方案的人
const markup = useCallback((count) => {
const stringCountCorrection = count + 1;
return (
// some markup referencing the sections prop
);
// useCallback dependency array
}, [sections]);
所以我不是在寻找与此问题相关的代码答案。如果可能的话,我正在寻找关于为什么会发生这种情况的详细解释。
我对原因更感兴趣,然后只是简单地找到解决问题的答案或正确方法。
为什么在 useEffect 依赖数组中传递一个在 useEffect 之外声明的函数会导致重新渲染,而状态和道具在所述函数中都没有改变。
问题是在每个渲染周期中,markup
都会被重新定义。 React 使用浅层对象比较来确定值是否更新。每个渲染周期 markup
都有不同的参考。您可以使用 useCallback
来记住该函数,这样引用就稳定了。您是否为 linter 启用了 react hook rules?如果你这样做了,它可能会标记它,告诉你原因,并提出这个建议来解决参考问题。
const markup = useCallback(
(count) => {
const stringCountCorrection = count + 1;
return (
// Some markup that references the sections prop
);
},
[count, /* and any other dependencies the react linter suggests */]
);
// No infinite looping, markup reference is stable/memoized
useEffect(() => {
if (sections.length) {
const sectionsWithMarkup = sections.map((section, index)=> markup(index));
setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
} else {
setSectionBlocks(blocks => []);
}
}, [sections, markup]);
Why is an infinite loop created when I pass a function expression
“无限循环”是组件一遍又一遍地重新渲染,因为 markup
函数是一个新的函数引用(内存中的指针),每次组件渲染并且 useEffect
触发重新渲染,因为它是一个依赖项。
解决方案正如@drew-reese 指出的那样,使用 useCallback
钩子来定义您的 markup
函数。