Search code examples
javascriptreactjsuse-state

What is the difference between [...arr, addThisElement], and arr.push(addThisElement) when using useState in ReactJS?


Could someone please explain the difference between this:

const arr = users;

arr.push({ firstName, email })

setUsers((prevState) => arr)

and this:

setUsers(prevState => [...prevState, { firstName, email }])

Solution

  • The answer is references and object equality...

    Array.prototype.push() mutates the array in place meaning its object reference does not change.

    const prevState = [1,2,3];
    const nextState = prevState;
    nextState.push(4);
    nextState === prevState; // true
    

    [...prevState, { firstName, email }] creates a new array which is not equal to prevState.

    const prevState = [1,2,3];
    const nextState = [...prevState, 4];
    nextState === prevState; // false
    

    As per React's state change detection rules...

    Bailing out of a dispatch

    If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)

    Using .push() and updating the state to the same value means React will bail out of the re-render and you won't see changes made.

    users.push({
      firstName: "Bob",
      email: "bob@example.com"
    });
    setUsers(users);
    

    Edit lucid-williamson-21sejq

    Create a new array and the changes are made visible

    setUsers((prev) => [
      ...prev,
      {
        firstName: "Bob",
        email: "bob@example.com"
      }
    ]);
    

    Edit keen-napier-hk5m5i