0

When I click on the add button the state updates but then the list still shows the same stuff. How do I fix it so that it updates with state?

I'm also using sortablejs but I removed it from the code since it doesn't seem to be relevant and I didn't want to clutter the code with unnecessary packages.

import React, { useState } from "react";

import { ListGroup } from 'react-bootstrap';


const DraggableList = () => {

  const [events, setEvents] = useState([
    { id: 1, name: "shrek" },
    { id: 2, name: "fiona" },
    { id: 3, name: "donkey" },
  ]);

  const addEvent = () => {
    let newEvents = events
    let event = {
      id: events.length + 1,
      name: "dragon",
    }
    newEvents.push(event)
    setEvents(newEvents)
    console.log(events)
  }

  return (
    <div>
      <button onClick={addEvent}>Add</button>
      {events.map((item) => (
        <ListGroup.Item key={item.id} action variant="success">{item.name}</ListGroup.Item>
      ))}
    </div>
  );
};

export default DraggableList
aaon
  • 5
  • 1
  • 1
    Number 1 rule of react: Don't mutate state. How'd the pattern of `let newState = oldState` get to be so widely perpetuated anyway? I literally see this on every second react question on SO. – Adam Jenkins May 05 '21 at 23:42
  • I thought by doing ```let newState = oldState``` I was avoiding mutating state. Is using setEvents not creating a new state? – aaon May 05 '21 at 23:47
  • Everybody thinks that, it's not true. You've just made the same reference available by a new name. After you do `let newState = oldState` write `console.log(newState === oldState)`. It's the same reference! So by modifying `newState`, you are mutating the existing state (see the rule number 1 above). By doing `newState = [...oldState]` you will see that `newState !== oldState`, so you are now free to do what you want with `newState` and know that you haven't mutated state. – Adam Jenkins May 05 '21 at 23:50
  • Ah alright that makes sense. Thanks! – aaon May 05 '21 at 23:53
  • 1
    @aaon as a heads up, the spread operator only does a **shallow** copy. So for an array of objects (since objects are stored by reference), yes the array itself will be a new one, but the objects inside will be the same ones in each array, i.e. editing one of the objects will change it in both arrays, since it's essentially the same object in memory – Jayce444 May 06 '21 at 00:33
  • @Jayce444 Ah thanks this could potentially prevent some future debugging troubles. Looks like I can copy the array with Array.from at a small performance cost. Good to know – aaon May 06 '21 at 01:29

1 Answers1

0

Because the pointer of the newEvents array never changes. Do let newEvents = [...events] and it should work

FireFighter
  • 686
  • 3
  • 6