0

We know that the useState hook is used for managing state within functional components in ReactJs.

So, for learning purposes I was implementing the example of the useState hook (snippet is given below) wherein I have taken an array with some initial value and I need to update the array and display the whole updated array in the browser whenever I clicked on the button. I tried with the below snippet but didn't get the expected result.

Problem: When I click the button for first time it will add the new element in the array but after clicking the button for two or more times it only overrides the last element.

Expected Result: New elements should be added in the array rather than overriding the last element in the array.

I definitely missing any logic or any important concept of useState hook here in this example. Please help me to understand more on react Hooks.

const {useState} = React;

const Example = () => {
    const array = [1,2,3] ;
    const [newArray,setNewArray] = useState(array);
    const [newElement,setElement]= useState(array[array.length-1]);

    const handleBoth = () => {
        setElement(prev => prev + 1);
        setNewArray([...array,newElement]);
    }

    const mapping = newArray.map(element => <li> No. {element}</li>)    

    return (
        <div>
            <ul>
                {mapping}
            </ul>
            <button onClick={handleBoth}>Add</button>
        </div>
    );
};

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Subrato Pattanaik
  • 5,331
  • 6
  • 21
  • 52

1 Answers1

1

Use the state newArray not the array for the map implementation. array will reinitialize to [1,2,3] on every render. In fact, you should just move the array constant outside of the component

const {useState} = React;
const array = [1,2,3];

const Example = () => {
    const [newArray,setNewArray] = useState(array);
    const [newElement,setElement]= useState(array[array.length-1]+1);

    const handleBoth = () => {
        setElement(prev => prev + 1);
        setNewArray([...newArray,newElement]);
    }

    const mapping = newArray.map(element => <li> No. {element}</li>)    

    return (
        <div>
            <ul>
                {mapping}
            </ul>
            <button onClick={handleBoth}>Add</button>
        </div>
    );
};

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
95faf8e76605e973
  • 13,643
  • 3
  • 24
  • 51
  • Thanks, Could you explain more about what was happening before? So next time I'll aware that something is misplaced. – Subrato Pattanaik Sep 23 '20 at 10:47
  • 1
    Yes, the issue is primarily regarding this statement that you had `setNewArray([...array,newElement]);`. Every re-render, React will go through the entire component, so `array` gets initialized back to `[1,2,3]` again. So when you are calling that `setNewArray` - everytime you call it, it simply doing this: `setNewArray([1,2,3,newElement]);` ... versus when using state - that value is not reinitalized everytime the component re-renders, it is only initially initialized when you call `useState`, so the state values will persist on renders – 95faf8e76605e973 Sep 23 '20 at 10:50
  • yeah, I clearly understood now what has happened before. Small doubt why did you add +1 here `useState(array[array.length-1]+1);`? – Subrato Pattanaik Sep 23 '20 at 11:21
  • 1
    Oh ok, your `array` is `[1,2,3]`. Therefore `array[array.length-1]` = 3. But when you append to the list you don't want to append 3 because this will happen --> `[1,2,3,3]`. You want to add 4. So that is the correct equation of `array[array.length-1]+1` – 95faf8e76605e973 Sep 23 '20 at 11:23
  • You have setted the newElement `setElement(prev => prev + 1);` just before setting the newArray `setNewArray([...newArray,newElement]);`. Why react is not updating the newElement when the button is clicked for the 1st time? Thanks – Subrato Pattanaik Sep 23 '20 at 11:52
  • 1
    https://stackoverflow.com/questions/42593202/why-calling-setstate-method-doesnt-mutate-the-state-immediately/42593250 – 95faf8e76605e973 Sep 23 '20 at 12:12
  • "setState is asynchronous" got it. Thanks – Subrato Pattanaik Sep 23 '20 at 13:55