Search code examples
reactjsformsobject

setState not updating an object straight away


I have a form and when the submit button is clicked I am trying to store the values from each field into an object so I can send the object in a POST request. The first time I click submit, I get the default state of the object with empty properties and then when I click it again, the object properties update. This keeps happening as I change the values in the input fields, it is always one step behind.

Here is the default state and the function that is replacing the object. This gets called in the button onClick.

const [formResponse, setFormResponse] = useState({
    name: "",
    projectTitle: "",
    projectDescription: "",
    projectGoal: "",
    projectOutcome: ""
  });

  function submitFormResponse(e) {
    e.preventDefault();
    setFormResponse((formResponse) => ({
      ...formResponse,
      name: name,
      projectTitle: title,
      projectDescription: description,
      projectGoal: goal,
      projectOutcome: outcome
    }));

    console.log(formResponse);
  }

Here is a codesandbox version of what's happening.

I can't figure out why this might be happening. Any help is greatly appreciated!


Solution

  • You cannot update the state immediately, From the docs

    State Updates May Be Asynchronous
    React may batch multiple setState() calls into a single update for performance.
    
    Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
    

    Check this

    //Here is your code modification
    import React, { useState } from "react";
    
    export default function Form() {
      const [name, setName] = useState("");
      const [title, setTitle] = useState("");
      const [description, setDescription] = useState("");
      const [goal, setGoal] = useState("");
      const [outcome, setOutcome] = useState("");
      const [formResponse, setFormResponse] = useState({
        name: "",
        projectTitle: "",
        projectDescription: "",
        projectGoal: "",
        projectOutcome: ""
      });
    
      function submitFormResponse(e) {
        e.preventDefault();
        // Create a object to hold values
        const formResult = {
          name: name,
          projectTitle: title,
          projectDescription: description,
          projectGoal: goal,
          projectOutcome: outcome
        }
        //Write post request logic and send `formResult`
    
        // setFormResponse((formResponse) => ({
        //   ...formResponse,
        //   name: name,
        //   projectTitle: title,
        //   projectDescription: description,
        //   projectGoal: goal,
        //   projectOutcome: outcome
        // }));
    
        console.log(formResult);
      }
    
      return (
        <form>
          <input
            name="name"
            type="text"
            placeholder="Name"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
          <input
            name="projectTitle"
            type="text"
            placeholder="Project title"
            value={title}
            onChange={(e) => setTitle(e.target.value)}
          />
          <textarea
            name="projectDescription"
            placeholder="Project description"
            value={description}
            onChange={(e) => setDescription(e.target.value)}
          ></textarea>
          <input
            name="goal"
            type="text"
            placeholder="Project goal"
            value={goal}
            onChange={(e) => setGoal(e.target.value)}
          />
          <textarea
            name="outcome"
            placeholder="Project outcome"
            value={outcome}
            onChange={(e) => setOutcome(e.target.value)}
          ></textarea>
          <button type="submit" onClick={submitFormResponse}>
            Submit
          </button>
        </form>
      );
    }