Skip to main content
useState returns a stateful value and a function to update it. The state persists between renders and updating it triggers a re-render of the component.

Signature

function useState<S>(
  initialState: S | (() => S)
): [S, Dispatch<StateUpdater<S>>]

function useState<S = undefined>(): [
  S | undefined,
  Dispatch<StateUpdater<S | undefined>>
]

Parameters

initialState
S | (() => S)
The initial value for the state, or a function that returns the initial value. If a function is provided, it will only be executed during the initial render (lazy initialization).

Returns

Returns a tuple containing:
  1. Current state value (S): The current state value
  2. State setter function (Dispatch<StateUpdater<S>>): A function to update the state. Can accept either:
    • A new state value directly
    • A function that receives the previous state and returns the new state

Basic Usage

import { useState } from 'preact/hooks';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Lazy Initialization

If computing the initial state is expensive, you can pass a function that will only be called during the initial render:
function ExpensiveComponent() {
  const [data, setData] = useState(() => {
    // This expensive calculation only runs once
    return computeExpensiveValue();
  });

  return <div>{data}</div>;
}

Functional Updates

When the new state depends on the previous state, use the functional form of the setter:
function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    // Using functional update ensures correct value
    setCount(prevCount => prevCount + 1);
  };

  return <button onClick={increment}>Count: {count}</button>;
}

Multiple State Variables

function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [age, setAge] = useState(0);

  return (
    <form>
      <input value={name} onChange={e => setName(e.target.value)} />
      <input value={email} onChange={e => setEmail(e.target.value)} />
      <input value={age} onChange={e => setAge(Number(e.target.value))} />
    </form>
  );
}

Object State

function UserProfile() {
  const [user, setUser] = useState({
    name: 'John',
    age: 30,
    email: '[email protected]'
  });

  const updateName = (newName) => {
    // Merge with previous state
    setUser(prevUser => ({
      ...prevUser,
      name: newName
    }));
  };

  return <div>{user.name}</div>;
}
State updates may be batched for performance. Multiple setState calls in the same event handler are batched together, resulting in a single re-render.
If you call the state setter with the same value as the current state (compared using Object.is), Preact will skip re-rendering the component and its children.

Build docs developers (and LLMs) love