React useEffect - 在依赖数组中传递一个函数 [英] React useEffect - passing a function in the dependency array

查看:110
本文介绍了React useEffect - 在依赖数组中传递一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么当我将函数表达式传递给 useEffect 依赖数组时会创建一个无限循环?函数表达式不会改变组件状态,它只是引用它.

Why is an infinite loop created when I pass a function expression into the useEffect dependency array? The function expression does not alter the component state, it only references it.

// 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]);

如果标记改变了状态,我可以理解为什么它会创建一个无限循环,但它不是简单地引用部分属性.

If markup altered state I could understand why it would create an infinite loop but it does not it simply references the sections prop.

对于那些正在寻找解决此问题的方法的人

For those looking for the solution to this problem

const markup = useCallback((count) => {
        const stringCountCorrection = count + 1;
        return (
            // some markup referencing the sections prop
        );
// useCallback dependency array
}, [sections]);

所以我不是在寻找这个问题的代码相关答案.如果可能,我正在寻找有关为什么会发生这种情况的详细解释.

So I'm not looking for a code related answer to this question. If possible I'm looking for a detailed explanation as to why this happens.

我更感兴趣的是为什么然后只是简单地找到答案或解决问题的正确方法.

I'm more interested in the why then just simply finding the answer or correct way to solve the problem.

为什么在 useEffect 依赖数组中传递在 useEffect 之外声明的函数会导致在所述函数中的 state 和 props 未更改时重新渲染.

Why does passing a function in the useEffect dependency array that is declared outside of useEffect cause a re-render when both state and props aren't changed in said function.

推荐答案

问题是在每个渲染周期中,markup 都会重新定义.React 使用浅层对象比较来确定值是否更新.每个渲染周期 markup 都有不同的引用.您可以使用 useCallback 来记住该函数,因此引用是稳定的.您是否为您的 linter 启用了 react hook 规则?如果您这样做了,它可能会标记它,告诉您原因,并提出此建议以解决参考问题.

The issue is that upon each render cycle, markup is redefined. React uses shallow object comparison to determine if a value updated or not. Each render cycle markup has a different reference. You can use useCallback to memoize the function though so the reference is stable. Do you have the react hook rules enabled for your linter? If you did then it would likely flag it, tell you why, and make this suggestion to resolve the reference issue.

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]);

这篇关于React useEffect - 在依赖数组中传递一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆