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!
CodePudding user response:
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.
//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>
);
}
CodePudding user response:
This is normal React behavior, state value changes happen asynchronously, to change synchronously you can use useRef hook, or you can use useEffect hook to listen for state changes and always get the latest value updated.