state not updating properly

import React, { useState } from "react";
import "../styles/App.css";
const App = () => {
const [shapes, setShapes] = useState([]);

const addShape = (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const shape = formData.get("selectShape");
const newShape = {
shape: shape,
};
setShapes([...shapes, newShape]);
console.log(shapes);
};

return (
<div id="main">
<div id="shape-creator">
<form onSubmit={addShape}>
<select defaultValue="Square" name="selectShape">
<option value="Square">Square</option>
<option value="Circle">Circle</option>
</select>
<button type="submit">Add Shape</button>
</form>
</div>
<div id="shapes-holder">
{/* {shapes.map((shape, index) => (
<Shape key={index} type={shape.type} id={shape.id} />
))} */}
</div>
</div>
);
};
import React, { useState } from "react";
import "../styles/App.css";
const App = () => {
const [shapes, setShapes] = useState([]);

const addShape = (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const shape = formData.get("selectShape");
const newShape = {
shape: shape,
};
setShapes([...shapes, newShape]);
console.log(shapes);
};

return (
<div id="main">
<div id="shape-creator">
<form onSubmit={addShape}>
<select defaultValue="Square" name="selectShape">
<option value="Square">Square</option>
<option value="Circle">Circle</option>
</select>
<button type="submit">Add Shape</button>
</form>
</div>
<div id="shapes-holder">
{/* {shapes.map((shape, index) => (
<Shape key={index} type={shape.type} id={shape.id} />
))} */}
</div>
</div>
);
};
on the first form, submission setShapes not getting updated. But the second form submission is updated by the previous value why is this happening?
6 Replies
Joao
Joaoβ€’8mo ago
Try with:
setShapes((previousState) => [...previousState, newShape]);
setShapes((previousState) => [...previousState, newShape]);
Updates to state in react are asynchronous, when you need to grab the current value you use the argument passed in to the set function.
glutonium
glutoniumβ€’8mo ago
in the state array u r setting object as array item for example newShape is an object which is being pushed to the state array but i see in the commented part of your code, in the html/jsx section u r doing shape.type or shape.id type id are not even a key in the object tho if you are talking about the console, that consoling the shape returns empty arragy then it's understandable i forgot why it happens but i think u can try with the function method of the setter function I don't completely remember but it was something like setState( preState => preState.push() ) or something
Chooβ™šπ•‚π•šπ•Ÿπ•˜
The recommendation to spread the previous value only solves half the problem. That ensures that the new state is properly based on the old one. However, the console log still will not work, because it runs synchronously. Setters are asynchronous but do not return a promise, so you cannot await them. The official recommended practice to get the console log to work is via useEffect with the state as the dependency.
glutonium
glutoniumβ€’8mo ago
i think if u put the console.log within the call back function of the setter logging out the previousState after it is updated, i think it'll work
Chooβ™šπ•‚π•šπ•Ÿπ•˜
In the callback, you can do a console log of the new value that you are instructing the setter to use, but that isn't exactly the same as outputting the new state value. I don't recall when the output will be different, but there are occasional differences, which is why useEffect is the official recommendation. I believe the problem arises when the state is set multiple times in rapid succession. Due to batching, only the final value is actually ever set. Since none of the intermediate values are actually set, the console logs from the callback will be outputting values that the state never had, except the final one in the sequence.
glutonium
glutoniumβ€’8mo ago
Hmm understandable react being the sh8 it always is -.-
Want results from more Discord servers?
Add your server