Complex Objects in State

With bigger applications, state will likely be more than just primitive values. It is more common to store arrays or objects as state. Arrays and objects in JavaScript, however, are mutable but for React to work properly they should be treated as if they were immutable. In plain terms, we should always replace the array or object in state with a new copy.

Using an Array as the State Value

import { useState } from "react";

const randInt = () => {
  return Math.floor(Math.random() * 84);
};

const App = () => {
  const [nums, setNums] = useState([4, 2]);

  const addNum = () => {};

  const removeOddNums = () => {};

  return (
    <div className="App">
      <button onClick={addNum}>Add num</button>
      <button onClick={removeOddNums}>Remove odd nums</button>
      <ul>
        {nums.map((n) => (
          <li>{n}</li>
        ))}
      </ul>
    </div>
  );
};

export default App;

Adding to the Array

Instead of using .push which will mutate the array, we use .concat or the ... spread operator to create a new array with the new number added at the end.

const addNum = () => {
  setNums([...nums, randInt()])
}

Removing from an Array

Use the .filter or .slice methods. Avoid .pop, .shift, and .splice unless you clone the array first.

const removeOddNums = () => {
  setNums(nums.filter((n) => n % 2 === 0))
}

Using an Object as the State Value

import { useState } from "react";

const App = () => {
  const [user, setUser] = useState({
    name: "Taylor Hebert",
    age: 18,
    capeName: "Skitter",
    team: "Undersiders",
  });

  const updateUser = () => {};

  return (
    <div className="App">
      <button onClick={updateUser}>Update User</button>
      <p>{user.name}</p>
      <p>{user.age}</p>
      <p>{user.capeName}</p>
      <p>{user.team}</p>
    </div>
  );
};

export default App;

Object Spread

Remember that we need to create a new copy of the state to trigger React's re-rendering. We can use the same ... spread operator we used on arrays to make a copy of an object. CAVEAT: For nested objects and arrays, ... only creates a shallow copy.

const updateUser = () => {
  setUser({
    ...user,
    name: "Lisa Wilbourne",
    capeName: "Tattletale",
  });
};

Last updated