State with useState

useState gives a component memory that persists between renders.

Syntaxconst [count, setCount] = useState(0);

State is data a component remembers between renders. You add state with the useState hook, which returns the current value and a function to update it.

How a state update works

Calling the setter tells React the value changed. React then re-renders the component with the new value, and the screen updates. State is not changed in place — you always call the setter.

The useState render cycle: initial render, an event calls the setter, React re-renders with the new state, and the DOM updatesRenderUIUsereventsetStatere-renderUpdateDOMloop on next interaction
Each state update triggers a re-render, and React updates only the parts of the DOM that changed.

Example

Example · javascript
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount((c) => c + 1)}>
      Clicked {count} times
    </button>
  );
}

When to use it

  • A shopping cart counter uses useState to track how many items have been added so the badge in the nav bar updates instantly on each click.
  • A multi-step wizard stores the current step index in useState and advances it when the user clicks Next, keeping the progress bar in sync.
  • A toggle component persists its open/closed state across renders with useState so collapsible sidebars stay open when the user navigates within the same session.

More examples

Counter with useState

Demonstrates the canonical useState pattern: reading the current value and calling the setter to trigger a re-render.

Example · jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  );
}

Functional updater for derived state

Uses the functional updater form (prev => prev + 1) to safely compute the next value from the previous state.

Example · jsx
import { useState } from 'react';

function LikeButton() {
  const [likes, setLikes] = useState(0);
  const handleLike = () => setLikes(prev => prev + 1);
  return <button onClick={handleLike}>Like ({likes})</button>;
}

Object state update pattern

Shows how to hold multiple fields in a single state object and update individual fields without losing the others.

Example · jsx
import { useState } from 'react';

function ProfileForm() {
  const [form, setForm] = useState({ name: '', email: '' });
  const update = field => e =>
    setForm(prev => ({ ...prev, [field]: e.target.value }));

  return (
    <form>
      <input value={form.name} onChange={update('name')} placeholder="Name" />
      <input value={form.email} onChange={update('email')} placeholder="Email" />
    </form>
  );
}

Discussion

  • Be the first to comment on this lesson.