简体   繁体   English

React:无法在 function 组件中更新 state 中的 object 属性

[英]React: Cannot update object property in state in function component

Problem I'm trying to solve: Form validation for an app built in React that takes in user input and generates a CV.我试图解决的问题:对一个内置 React 的应用程序进行表单验证,该应用程序接受用户输入并生成 CV。 This is for learning purposes and part of The Odin Project curriculum.这是为了学习目的,也是奥丁计划课程的一部分。

How I'm trying to solve form validation: I have my project organized with a large formData object set as state in App.js and I'm sharing that state to all child components via useContext.我是如何尝试解决表单验证问题的:我在 App.js 中使用大型 formData object 设置为 state 来组织我的项目,并且我通过 useContext 将 state 共享给所有子组件。 For validation, I have given each piece of CV data 2 properties in my formData object. Example below:为了验证,我在我的 formData object 中为每条 CV 数据提供了 2 个属性。示例如下:

{firstname: '', firstNameValid: true}

I am trying to write a function (see attached code) that sets the validity of each propertyValid and set it to false.我正在尝试编写一个 function(请参阅附加代码)来设置每个 propertyValid 的有效性并将其设置为 false。

What I expect: When a field is invalid (like firstName), it sets firstNameValid: false when I run the invalidateField('firstName') function.我的期望:当一个字段无效(如 firstName)时,它会在我运行invalidateField('firstName') function 时设置firstNameValid: false

What happens instead: Logging the formData reveals that firstNameValid is still set to true .相反会发生什么:记录 formData 显示firstNameValid仍设置为true

What I have tried: As seen in the attatched code, I am trying to make a copy of my formData object, set only the value I want, and then just manually set it using setFormData(formCopy) .我尝试了什么:如附加代码所示,我正在尝试复制我的 formData object,仅设置我想要的值,然后使用setFormData(formCopy)手动设置它。 However, when I log them together, I see that while formCopy looks like what I want it to be, the formData in state still has not changed.但是,当我将它们记录在一起时,我看到虽然 formCopy 看起来像我想要的那样,但 state 中的 formData 仍然没有改变。 I am updating state just fine from my grandchildren components, but I'm unable to do it here and I don't understand why.我正在从我的孙子组件更新 state,但我无法在此处执行此操作,我不明白为什么。

//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.

The setFormData method is an async function. It takes a while until the state is updated. setFormData 方法是一个异步的 function。需要一段时间才能更新 state。 You console.log right after calling setFormData, thats why it looks as if your setState didnt work properly when it just needs a little more time to complete.您在调用 setFormData 后立即使用 console.log,这就是为什么它看起来好像您的 setState 没有正常工作,只是需要更多时间才能完成。

Above your invalidateField function you could write an useEffect to print out when your state has changed:在您的 invalidateField function 上方,您可以编写一个 useEffect 以在您的 state 发生更改时打印出来:

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

This will execute the console.log as soon as formData has changed.这将在 formData 更改后立即执行 console.log。

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

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