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

问题描述

案例 1:

 const [present, setPresent] = useState([]);useEffect(() => {for (var j = 1; j 

情况 2:

.

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 钩子不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 12:30