【问题标题】:react setstate does not work properly on loopsreact setstate 在循环中无法正常工作
【发布时间】:2020-12-18 22:38:37
【问题描述】:

我从后端收到一个像这样的数组的验证响应

 [
        { param: "secondName", msg: "second name is required" },
        { param: "password", msg: "password is required" }
 ]

我的反应组件中有这样的状态

  const [errs, setErrs] = useState({
    firstName: null,
    secondName: null,
    password: null,
    email: null,
  })

目标是在我的状态下仅更改表单提交时response.params 中提到的字段,而将其余字段保留为null。 这是我尝试过的:

const submitFoo = () => {
    console.log(localErrs) //all props are set to null (default)
    res.forEach((single) => {
        setLocalErrs({
            ...localErrs,
            [single.param]: single.msg
        });
    });
    console.log(localErrs);//only password is set to the `response.msg`, instead of `password` AND `secondName`
};

但问题是它只改变了我的“错误状态”中的最后一项; 输出是:

{
    first: null,
    second: null,
    password: 'password is required',
    email: null,
}

ps:我通过遍历数组并将 Errs obj 的 props 直接设置为 response.msg 来尝试使用 vanilla js 并且它有效。所以prolem必须与react setstate有关

【问题讨论】:

    标签: reactjs validation react-hooks setstate use-state


    【解决方案1】:

    尝试使用 Fat Arrow 方法设置状态如下:

    setLocalErrs(localErrs => ({ ...localErrs, [single.param]: single.msg }));
    

    避免由于不同的异步调用等原因同时调用两次setter函数时的状态丢失。

    【讨论】:

      【解决方案2】:

      避免更新state in a loop。更新状态如下:

      let errObj = {}
      res.forEach((single) => {
        errObj[single.param] = single.msg
      })
      setLocalErrs({
        ...localErrs,
        ...errObj
      })
      

      顺便说一句,你可以简单地使用:

      setLocalErrs(errObj)
      

      由于errObj 具有所有更新的状态值。

      【讨论】: