简体   繁体   English

在useEffect中使用setState时如何防止我的React代码中的无限循环

[英]How to prevent infinite loop in my React code when using setState inside useEffect

Please check the codesandbox: https://codesandbox.io/s/bold-hamilton-k1nzs请检查代码框: https://codesandbox.io/s/bold-hamilton-k1nzs

Moment I run the code I am getting an infinite loop, you can check the console to see how the entries increase exponentially.在我运行代码的那一刻,我得到一个无限循环,您可以检查控制台以查看条目如何呈指数增长。 And eventually the website crashes.最终网站崩溃。

I have a state variable like this:我有一个像这样的 state 变量:

const [checkbox, setCheckBox] = useState({});

Then I am calling a function inside useEffect:然后我在useEffect里面调用一个function:

useEffect(() => {
    createCheckbox();
  });

This is the createCheckbox function:这是 createCheckbox function:

const createCheckbox = () => {
    let checkboxObj = {};
    rows.forEach((e) => {
      checkboxObj[e.id] = false;
    });
    setCheckBox(checkboxObj);
  };

I have a console.log at line 76 to showcase the problem.我在第 76 行有一个 console.log 来展示这个问题。 It is console.log(checkbox)它是 console.log(checkbox)

Any idea what is going on?知道发生了什么吗?

Use a dependency array for useEffect .useEffect使用依赖数组。 So this:所以这:

  useEffect(() => {
    createCheckbox();
  });

Should be:应该:

  useEffect(() => {
    createCheckbox();
  }, []);

useEffect() , as you already know, accepts a dependency array as the second parameter.如您所知, useEffect()接受一个依赖数组作为第二个参数。 It will only run when any of the variables in the array change.它只会在数组中的任何变量发生变化时运行。 When you run useEffect without the second parameter, it acts as componentDidMount and componentDidUpdate.当您在没有第二个参数的情况下运行useEffect时,它充当 componentDidMount 和 componentDidUpdate。 So since you set a state in your dependency-less useEffect, the state change triggers it again and again thus creating an infinite loop of renders.因此,由于您在无依赖的 useEffect 中设置了 state,因此 state 更改会一次又一次地触发它,从而创建无限循环的渲染。

When calling useEffect with an empty dependency array, it will only run once on first render.当使用空的依赖数组调用useEffect时,它只会在第一次渲染时运行一次。 And that's what you needed.这就是你所需要的。

Issue问题

useEffect(() => {
  createCheckbox();
});

The useEffect hook has no dependency so it runs every time the component renders, and since the hook callback ultimately updates state, it triggers another render cycle. useEffect hook 没有依赖关系,因此每次组件渲染时都会运行,并且由于 hook 回调最终会更新 state,它会触发另一个渲染周期。 Rinse and repeat, ad nauseam (ie render looping).冲洗并重复,令人作呕(即渲染循环)。

Solution解决方案

Basically I want to initialize the checkbox as empty/false on first load.基本上我想在第一次加载时将复选框初始化为空/假。

You can use an useEffect with empty dependency array to run the effect once when the component mounts.您可以使用带有空依赖数组的useEffect在组件挂载时运行一次效果。

useEffect(() => {
  createCheckbox();
}, []);

Or use lazy state initialization function with the useState hook.或者使用懒惰的 state 初始化 function 和useState钩子。

const [checkbox, setCheckBox] = useState(() => {
  let checkboxObj = {};
  rows.forEach((e) => {
    checkboxObj[e.id] = false;
  });
  return checkboxObj;
});

Demo演示

编辑 how-to-prevent-infinite-loop-in-my-react-code-when-using-setstate-inside-useeffe

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM