Arrays in State

Arrays are reference types and so you cannot change their state, you must treat them as immutable. Create a new copy of the array, modify it, and set that as the new state.

avoid (mutates the array)prefer (returns a new array)
addingpushunshiftconcat[...arr] spread syntax (example)
removingpopshiftsplicefilterslice (example)
replacingsplicearr[i] = ... assignmentmap (example)
sortingreversesortcopy the array first (example)

Add

setArtists( // Replace the state
  [ // with a new array
    ...artists, // that contains all the old items
    { id: nextId++, name: name } // and one new item at the end
  ]
);

Remove

setArtists(
  artists.filter(a => a.id !== artist.id)
);

Replacing

const nextCounters = counters.map((c, i) => {
  if (i === index) {
    return c + 1;
  } else {
    return c;
  }
});

Insert

const insertAt = 1; // Could be any index
const nextArtists = [
  // Items before the insertion point:
  ...artists.slice(0, insertAt),
  // New item:
  { id: nextId++, name: name },
  // Items after the insertion point:
  ...artists.slice(insertAt)
];
setArtists(nextArtists);
setName('');

Sorting & Mutation

const nextList = [...list];
nextList.reverse();
setList(nextList);

Objects within arrays

You want to create new nested objects

setMyList(myList.map(artwork => {
  if (artwork.id === artworkId) {
    // Create a *new* object with changes
    return { ...artwork, seen: nextSeen };
  } else {
    // No changes
    return artwork;
  }
}));

Objects with immer

import { useImmer } from 'use-immer';

const [myTodos, updateMyTodos] = useImmer(initialList);

updateMyTodos(draft => {
  const artwork = draft.find(a => a.id === artworkId);
  artwork.seen = nextSeen;
});