NelsonLabs
React Fundamentals/State with useState

State with useState

State is data that can change over time and that, when it changes, causes React to re-render the component. It's the mechanism behind every interactive UI element — a toggle, a counter, a form input, a loading spinner.

ANALOGY

State is a component's memory. A component without state is like a vending machine with no display — it does what you tell it, but it can't remember anything between interactions. State gives your component memory. When state changes, the component re-renders itself to show the new data.

useState — the state hook
jsx
import { useState } from "react";

function Counter() {
  // useState returns: [currentValue, setterFunction]
  const [count, setCount] = useState(0);  // 0 is the initial value

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>−</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}
State with objects
jsx
function UserProfile() {
  const [user, setUser] = useState({
    name: "Nelson",
    role: "engineer",
    isActive: true,
  });

  function toggleActive() {
    // Always create a new object — don't mutate state directly
    setUser({ ...user, isActive: !user.isActive });
  }

  function updateName(newName) {
    setUser(prev => ({ ...prev, name: newName }));
    // Using prev is safer when the new state depends on the old state
  }

  return (
    <div>
      <p>{user.name} — {user.role}</p>
      <p>{user.isActive ? "Active" : "Inactive"}</p>
      <button onClick={toggleActive}>Toggle</button>
    </div>
  );
}

WARNING

Never mutate state directly. Don't do user.isActive = true or list.push(item). React detects state changes by comparing references. If you mutate the existing object/array, the reference doesn't change, React doesn't detect a change, and the UI doesn't update. Always create new values with spread, map, filter, etc.