bjects-with-the-spread-
syntax)

With this approach, none of the existing state items are being mutated, and
the bug is fixed:

App.js

App.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { useState } from 'react';
    
    let nextId = 3;
    const initialList = [
      { id: 0, title: 'Big Bellies', seen: false },
      { id: 1, title: 'Lunar Landscape', seen: false },
      { id: 2, title: 'Terracotta Army', seen: true },
    ];
    
    export default function BucketList() {
      const [myList, setMyList] = useState(initialList);
      const [yourList, setYourList] = useState(
        initialList
      );
    
      function handleToggleMyList(artworkId, nextSeen) {
        setMyList(myList.map(artwork => {
          if (artwork.id === artworkId) {
            // Create a *new* object with changes
            return { ...artwork, seen: nextSeen };
          } else {
            // No changes
            return artwork;
          }
        }));
      }
    
      function handleToggleYourList(artworkId, nextSeen) {
        setYourList(yourList.map(artwork => {
          if (artwork.id === artworkId) {
            // Create a *new* object with changes
            return { ...artwork, seen: nextSeen };
          } else {
            // No changes
            return artwork;
          }
        }));
      }
    
      return (
        <>
          <h1>Art Bucket List</h1>
          <h2>My list of art to see:</h2>
          <ItemList
            artworks={myList}
            onToggle={handleToggleMyList} />
          <h2>Your list of art to see:</h2>
          <ItemList
            artworks={yourList}
            onToggle={handleToggleYourList} />
        </>
      );
    }
    
    function ItemList({ artworks, onToggle }) {
      return (
        <ul>
          {artworks.map(artwork => (
            <li key={artwork.id}>
              <label>
                <input
                  type="checkbox"
                  checked={artwork.seen}
                  onChange={e => {
                    onToggle(
                      artwork.id,
                      e.target.checked
                    );
                  }}
                />
                {artwork.title}
              </label>
            </li>
          ))}
        </ul>
      );
    }
    
    

Show more

In general, **you should only mutate objects that you have just created.** If
you were inserting a _new_ artwork, you could mutate it, but if you’re dealing
with something that’s already in state, you need to make a copy.

###  Write concise update logic with Immer

Updating nested arrays without mutation can get a little bit repetitive. [
Just as with objects ](/learn/updating-objects-in-state#write-concise-update-
logic-with-immer) :

  * Generally, you shouldn’t need to update state more than a couple of levels deep. If your state objects are very deep, you might want to [ restructure them differently ](/learn/choosing-the-state-structure#avoid-deeply-nested-state) so that they are flat. 
  * If you don’t want to change your state structure, you might prefer to use [ Immer ](https://github.com/immerjs/use-immer) , which lets you write using the convenient but mutating syntax and takes care of producing the copies for you. 

Here is the Art Bucket List example rewritten with Immer:

package.json  App.js

package.json

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    {
      "dependencies": {
        "immer": "1.7.3",
        "react": "latest",
        "react-dom": "latest",
        "react-scripts": "latest",
        "use-immer": "0.5.1"
      },
      "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test --env=jsdom",
        "eject": "react-scripts eject"
      },
      "devDependencies":