【问题标题】:React: Cannot update object property in state in function componentReact:无法在功能组件中更新状态中的对象属性
【发布时间】:2023-01-20 02:01:58
【问题描述】:

我试图解决的问题:在 React 中构建的应用程序的表单验证,该应用程序接受用户输入并生成 CV。这是为了学习目的,也是奥丁计划课程的一部分。

我如何尝试解决表单验证问题:我的项目组织有一个大型 formData 对象,在 App.js 中设置为状态,我通过 useContext 将该状态共享给所有子组件。 为了进行验证,我在 formData 对象中为每条 CV 数据赋予了 2 个属性。下面的例子:

{firstname: '', firstNameValid: true}

我正在尝试编写一个函数(参见附加代码)来设置每个 propertyValid 的有效性并将其设置为 false。

我期望的是:当字段无效时(如 firstName),它会在我运行 invalidateField('firstName') 函数时设置 firstNameValid: false

相反会发生什么:记录 formData 显示 firstNameValid 仍设置为 true

我试过的:如附加代码所示,我正在尝试制作我的 formData 对象的副本,仅设置我想要的值,然后使用 setFormData(formCopy) 手动设置它。但是,当我将它们记录在一起时,我看到虽然 formCopy 看起来像我想要的那样,但 state 中的 formData 仍然没有改变。我正在从我的孙子组件中更新状态,但我无法在此处执行此操作,而且我不明白为什么。

//my object declared in state
  const [formData, setFormData] = React.useState({
    firstName: '',
    lastName: '',
    email: '',
    firstNameValid: true,
    lastNameValid: true,
    emailValid: true
    //a lot more than this but you get the idea
  });

//function in question that is not working
  function invalidateField(string){
    //takes the name of the key as a string
    let key = `${string}Valid`;
    let value = false;
    let formCopy = {...formData};
    formCopy[key] = value;
    
    setFormData(formCopy);
    console.log(formCopy, formData);
  }

//function I'm writing to check validity of input fields
//called by button click elsewhere in code
  function formIsValid(formData){
    let validity = true;
    if(formData.firstName.length < 1){     //firstName = '' (field is empty)
      console.log('your first name is too short');
      invalidateField('firstName');
      validity = false;
    }
    return validity;
  }


//context then passed to child components in the return statement.

【问题讨论】:

  • 我第一次研究我的问题时看到了这篇文章,但它并没有真正帮助。我在我的子组件中使用非常相似的方法更新状态,并且更改总是立即反映出来。我对 React 很陌生,所以我不完全理解闭包的含义,但我认为它不适用于这种情况。

标签: javascript reactjs react-hooks javascript-objects react-functional-component


【解决方案1】:

setFormData 方法是一个异步函数。状态更新需要一段时间。您在调用 setFormData 后立即使用 console.log,这就是为什么它看起来好像您的 setState 没有正常工作,只是需要更多时间才能完成。

在您的 invalidateField 函数之上,您可以编写一个 useEffect 以在您的状态发生变化时打印出来:

 import { useEffect } from "react";
    
    useEffect(() => {
      console.log(formData);
    }, [formData]);

这将在 formData 更改后立即执行 console.log。

【讨论】:

  • 谢谢,我会试试这个,看看它是否有效。我没有意识到所有 setState 函数都是异步的。
猜你喜欢
  • 2020-01-04
  • 2020-07-27
  • 2020-11-22
  • 1970-01-01
  • 2021-05-28
  • 2020-08-12
  • 1970-01-01
  • 2020-04-25
  • 2021-03-19
相关资源
最近更新 更多