How to Update Arrays in React State

Update arrays in React state by replacing them with new arrays. Use spread, filter, map, and slice instead of push and splice.

5 min read

To update arrays in React state, replace the array with a new one instead of mutating it. Methods like push and splice change the existing array, so React skips the update. Build the new array with spread, filter, map, and slice instead, the same way you replace objects.

Treat arrays as read-only

Arrays in JavaScript are objects, and the same read-only rule applies. Mutating methods change the old array in place, which hides the change from React. The list below maps each common task to the method that returns a new array instead.

TaskAvoid (mutates)Prefer (returns a new array)
Add an itempush, unshiftspread, concat
Remove an itempop, shift, splicefilter, slice
Replace an itemsplice, arr[i] = valuemap
Sort or reversesort, reversecopy first

The table is your quick reference. Every left-hand method changes the original array, and every right-hand option produces a fresh one. When in doubt, copy first and change the copy.

Add an item

Start with a list in state and spread it into a new array with the extra item at the end.

App.jsxApp.jsx
import { useState } from "react";
 
const [todos, setTodos] = useState([
  { id: 0, title: "Buy milk", done: false },
]);

Calling the setter with a spread creates the next list without touching the old one. The spread copies the existing items and appends the new item at the end.

App.jsxApp.jsx
setTodos([...todos, { id: 1, title: "Write tests", done: false }]);

The new array keeps the milk item and adds the tests item. React sees a different array, re-renders, and the list shows both. Prepend instead by placing the new item before the spread, and the existing items slide to the end.

Remove an item

Use filter to produce an array without the removed item. The callback returns true for items you want to keep and false for the one you are removing.

App.jsxApp.jsx
setTodos(todos.filter((todo) => todo.id !== 1));

The result contains every todo except the one with id 1. filter never modifies the original array, so the previous list stays intact for React's comparison and the next render receives a different array. slice works the same way when you only need to drop items from one end.

Replace an item

Use map to return a new item in place of the old one. The callback receives each item and decides whether to return it unchanged or return a replacement.

App.jsxApp.jsx
setTodos(
  todos.map((todo) =>
    todo.id === 1 ? { ...todo, done: true } : todo
  )
);

Only the matching item is replaced, and it is replaced with a copied object rather than mutated. The other items are returned as they were, so their identity stays the same and React can skip re-rendering anything that did not change.

Insert at a position and reorder

Spread plus slice inserts an item at any index.

App.jsxApp.jsx
setTodos([
  ...todos.slice(0, 1),
  { id: 2, title: "New item", done: false },
  ...todos.slice(1),
]);

The slice before the insertion point comes first, then the new item, then the rest. To reorder, copy the array first, then call sort or reverse on the copy, because both methods mutate their input. The full set of move and reorder operations is covered in removing, replacing, and reordering array items.

Common mistakes

These three slips produce the same silent symptom: the list never updates.

  • Calling push or splice directly on state mutates it and skips the render.
  • Copying the array but mutating an object inside it still mutates shared data.
  • Using the index as a key breaks when the list is reordered, inserted into, or filtered, so use stable keys from the data.

What to learn next

Arrays often hold objects, so updating objects is the natural next skill. Both follow the same rule: never mutate, always replace. For deeply nested lists, Immer removes the copying ceremony once the plain methods feel repetitive.

Rune AI

Rune AI

Key Insights

  • Never call push, pop, splice, sort, or reverse on state directly.
  • Add items with spread or concat.
  • Remove items with filter or slice.
  • Replace items with map.
  • Copy the array first before sorting or reversing.
RunePowered by Rune AI

Frequently Asked Questions

Why does push not update my list?

push changes the existing array, so the reference stays the same and React skips the render. Pass a new array to the setter instead.

How do I sort or reverse an array in state?

Copy the array first with spread, then call sort or reverse on the copy. The original array stays untouched.

Can I mutate an object inside a copied array?

No. Copying the array is shallow, so the items are still shared. Use map to replace the item with a copied object.

Conclusion

Arrays in state are read-only. Add with spread or concat, remove with filter or slice, and replace with map. Copy first for sort and reverse, and never mutate the original.