0

I have this fairly simple code.
When I press the button I want to push a new exercise object to the exercises state array.
But only the second time I press the button an object is added...

import React, { useState } from "react";
import { Button } from "react-bootstrap";

const EditorMenuPage = () => {
    const [exercises, setExercises] = useState([]);

    const addNewExercise = () => {
        const exercise = {
            exercise: "",
            duration: {
                active: "None",
                sets: null,
                reps: null,
                ...,
            },
            ...,
        };

        setExercises(() => [...exercises, exercise]);
        console.log(exercises);
    };

    return (
        <Button onClick={addNewExercise}>
            Add exercise
        </Button>
};

export default EditorMenuPage;

The console looks like this after pressing the button a couple of times:
enter image description here
The first log is empty I want this to already contain one exercise object

pluto9800
  • 247
  • 3
  • 12
  • 2
    `setExercises` sets the value async, so it is not guaranteed to be updated until the next render cycle. This means that your `console.log` is logging the old value. – Jacob Smit Mar 08 '21 at 20:07
  • I answered this question [here](https://stackoverflow.com/questions/66493111/cant-save-the-value-of-textbox-in-first-button-click-reactjs/66493391#comment117613539_66493391). In short, React don't know anything about your `exercises` variable. When you call `setState` react will change state somewhere in it's internals and call your component with new state. At this point you will assign this state to _new_ variable `exercises` that react again don't know about. – Mr. Hedgehog Mar 08 '21 at 20:09
  • Does this answer your question? [Cant save the value of textbox in first button click reactjs](https://stackoverflow.com/questions/66493111/cant-save-the-value-of-textbox-in-first-button-click-reactjs) – Mr. Hedgehog Mar 08 '21 at 20:10
  • In react, enqueued state updates are asynchronously processed ***between*** render cycles. The console log of the state you just enqueued an update for is still the state value from the ***current*** render cycle. Use an `useEffect` hook to log state once it's updated and the component rerendered. – Drew Reese Mar 08 '21 at 20:14
  • What @JacobSmit said above is spot on. Also, you should not pass a function to the `setExercises`. this will set your `exercises` value to be a function and not an array which will cause problems. Change the way you update your exercises to `setExercises([...exercises, exercise]);` to set the array directly (i.e. remove the fat arrow function) – RobCop Mar 08 '21 at 20:22
  • @RobCop [Functional state updates](https://reactjs.org/docs/hooks-reference.html#functional-updates) are completely valid syntax, and is technically the correct usage here since the array from the previous state is being updated (though not implemented correctly since OP is still spreading the current state). It ***should*** be `setExercises(exercises => [...exercises, exercise])`. Just about *any* time the next state depends on *any* previous state you should be using a functional update. – Drew Reese Mar 08 '21 at 20:58
  • @DrewReese noted, thanks for the correction – RobCop Mar 08 '21 at 22:52

0 Answers0