为什么在 useEffect() 中使用循环时 useState 钩子不更新 [英] Why useState hook don't update while using loop inside useEffect()

查看:95
本文介绍了为什么在 useEffect() 中使用循环时 useState 钩子不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

案例 1:

 const [present, setPresent] = useState([]);useEffect(() => {for (var j = 1; j <= totalPeriod; j++) {setPresent([...展示,{时期:j,现在:真实,},]);}}, []);

情况 2:

<预><代码>const [present, setPresent] = useState([]);让 createPresent = [];for (var j = 1; j <= totalPeriod; j++) {创建当前 = [...创建当前,{时期:j,现在:真实,},]}useEffect(() => {setPresent(createPresent);}, []);

当我尝试在案例 1 中使用 useEffect() 内部的循环更新 present 状态时,present 状态未更新.但是,当我在 useEffect() 之外单独使用循环并创建一个数组时,然后我将其分配给 present 状态,在情况 2 中,present> 状态正在更新.

这背后的原因是什么?为什么在案例 1 中当前状态没有更新?

解决方案

在以下情况下,您的 present 状态不是每个后续状态更新的结果,而是您拥有的初始状态是 [].React 将批量这些更新,而不是让它们同步发生,所以只有一个状态更新,present 更新到 for 循环.

 const [present, setPresent] = useState([]);useEffect(() => {for (var j = 1; j <= totalPeriod; j++) {setPresent([...展示,{时期:j,现在:真实,},]);}}, []);

在下面的例子中,你首先用你需要的所有值组装一个 createPresent 数组,最后调用状态更新器函数,即 setPresent 设置状态.

const [present, setPresent] = useState([]);让 createPresent = [];for (var j = 1; j <= totalPeriod; j++) {创建当前 = [...创建当前,{时期:j,现在:真实,},]}useEffect(() => {setPresent(createPresent);}, []);

为了用第一个实现第二个行为,您可以使用 状态更新器回调,它将前一个状态作为参数,如下所示:-

 const [present, setPresent] = useState([]);useEffect(() => {for (让 j = 1; j <= totalPeriod; j++) {setPresent(prevState=>[...prevState,{时期:j,现在:真实,},]);}}, []);

这里的状态更新也是批量,但在更新下一个状态之前会考虑之前的状态.

当我说批量状态更新时,我的意思是只有一个渲染.您可以通过在组件的函数体中执行 console.log('render') 来验证这一点.

注意这里使用 let 而不是 var,因为 let 是有范围的,您将获得变量 j 的准确值.

Case 1:

    const [present, setPresent] = useState([]);
     
    useEffect(() => {
    
        for (var j = 1; j <= totalPeriod; j++) {
          setPresent([
            ...present,
            {
              period: j,
              present: true,
            },
          ]);
        }
    
    }, []);

Case 2:


    const [present, setPresent] = useState([]);
    
    let createPresent = [];
    for (var j = 1; j <= totalPeriod; j++) {
      createPresent = [
        ...createPresent,
        {
          period: j,
          present: true,
        },
      ]
    }
    
    useEffect(() => {
      setPresent(createPresent);
    }, []);

When I am trying to update the present state using loop in inside useEffect() in Case 1, present state is not updating. But when I am separately using loop outside the useEffect() and creating an array which I am then assigning to present state in case 2, the present state is getting updated.

What is the reason behind this? Why present state is not updating in Case 1?

解决方案

In the below case, your present state is not the result of each subsequent state update but rather the initial one which you had which is []. React will batch these updates and not make them happen synchronously so effectively there will be just one state update with present updated to latest entry in your for loop.

  const [present, setPresent] = useState([]);
     
    useEffect(() => {
    
        for (var j = 1; j <= totalPeriod; j++) {
          setPresent([
            ...present,
            {
              period: j,
              present: true,
            },
          ]);
        }
    
    }, []);

In the below case, you are first assembling a createPresent array with all the values you need and finally calling the state updator function i.e. setPresent to set the state.

const [present, setPresent] = useState([]);
    
    let createPresent = [];
    for (var j = 1; j <= totalPeriod; j++) {
      createPresent = [
        ...createPresent,
        {
          period: j,
          present: true,
        },
      ]
    }
    
    useEffect(() => {
      setPresent(createPresent);
    }, []);

In order to achieve the second behaviour with first, you can make use of the state updator callback which holds the previous state as the argument like so :-

  const [present, setPresent] = useState([]);
     
    useEffect(() => {
    
        for (let j = 1; j <= totalPeriod; j++) {
          setPresent(prevState=>[
            ...prevState,
            {
              period: j,
              present: true,
            },
          ]);
        }
    
    }, []);

Here also state update is batched but previous state is factored in before updating the next one.

When I say a batched state update, I mean there will only be a single render. You can verify that by doing console.log('render') in your component's function body.

Note the use of let instead of var here since let is scoped you will get the accurate value for the variable j.

这篇关于为什么在 useEffect() 中使用循环时 useState 钩子不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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