Immutable updates to react state

By May 23, 2019Uncategorized

Photo by Lwin Kyaw Myat on Unsplash

I spent an hour yesterday trying to figure out why my React component using useState and hooks wasn’t updating when it appeared the state was updating.

Ultimately the problem was that I wasn’t immutably updating the state, I was mutating a reference to the original state, and React only re-renders if it sees the state changing.

This is how I had the code, when it wasn’t working.

...
const [thoughts, setThoughts] = userState(null);

useEffect ( () => {
  if (!user) setThoughts(null);

  if (user) {
    
    <load data>

  }

}, [user]);

// handle edit of a thought
const handleEdit = (docId, event) => {
  ...
  let newThoughts = thoughts;
  newThoughts[docId][event.target.name] = event.target.value;
  setThoguhts(newThoughts);
};

return (

   <editable table>

);


While debugging, I had a console.log(thoughts) after line 20, which indicated that the state was being updated, but the component never re-rendered.

The problem was line 18.

In javascript this just sets newThoughts as a reference to the same object as thoughts. As long as React is concerned, when you update newThoughts, you’re updating thoughts. When you setThoughts(newThoughts), newThoughts is exactly the same as thoughts so nothing has changed, and no re render is necessary.

Fortunately an easy fix. just change line 18 as follows.

let newThoughts = { ... thoughts ]:

This creates a copy of thoughts as newThoughts. Then, when setThoughts(newThoughts) is called, newThoughts is different to thoughts and React re-renders the component.