Back to Interview PrepGet interview ready with AILearn each topic the way interviewers ask it, then answer like you would in the interview.
Course progress0/14 chapters · 0%

Chapter 3 of 15

~12 min

State & useState

State is data a component owns and can change over time, and `useState` is the hook that gives function components that ability. Whenever a piece of data changes and the UI needs to reflect it, that data belongs in state.

Why Props Alone Are Not Enough

Props let a component receive data, but they cannot change on their own from inside the component. State is different - it is local, mutable (through a setter, never directly), and updating it triggers React to re-render the component with the new value.

Declaring State with useState

`useState(initialValue)` returns a pair: the current value and a function to update it, conventionally destructured as `const [value, setValue] = useState(initialValue)`. Calling the setter schedules a re-render with the new value - it does not mutate the variable in place.

Try it yourself

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

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}

render(<Counter />);
Output

State Updates Are Asynchronous and Batched

Calling the setter does not update `count` immediately in the current render - it schedules the update for the next render. React also batches multiple state updates that happen in the same event handler into a single re-render for performance, so logging the state variable right after calling its setter will still show the old value.

Functional Updates

When a new state value depends on the previous one, pass a function to the setter instead of a value: `setCount(prev => prev + 1)`. This guarantees you are always working from the most recent state, which matters especially when multiple updates happen close together (like several rapid clicks, or updates inside async code).

Try it yourself

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

  const incrementTwice = () => {
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementTwice}>+2</button>
    </div>
  );
}

render(<Counter />);
Output

Count: 0

Each useState Call Is Independent

A component can call `useState` multiple times, each managing its own independent piece of state. There is no requirement to bundle everything into one big state object - in fact, splitting unrelated values into separate `useState` calls is usually simpler than merging them.

Try it yourself

function ProfileForm() {
  const [name, setName] = useState('');
  const [isSubscribed, setIsSubscribed] = useState(false);

  return (
    <div>
      <input value={name} onChange={e => setName(e.target.value)} placeholder="Name" />
      <p>Hello, {name || 'stranger'}!</p>
      <label>
        <input
          type="checkbox"
          checked={isSubscribed}
          onChange={e => setIsSubscribed(e.target.checked)}
        />
        Subscribe
      </label>
      <p>Subscribed: {isSubscribed ? 'yes' : 'no'}</p>
    </div>
  );
}

render(<ProfileForm />);
Output

Hello, stranger!

Subscribed: no

State With Objects and Arrays

When state holds an object or array, you must replace it with a new object/array rather than mutating it in place - React compares references to decide whether to re-render, so `state.push(x)` followed by `setState(state)` will not trigger an update. Use spread syntax instead: `setItems([...items, newItem])`.

Coding challenge

Build a Toggle component with a boolean state starting at false. Render a button that shows "ON" or "OFF" depending on the state, and flips it on click using a functional update.

function Toggle() {
  // write your code here
  return null;
}

render(<Toggle />);
Output

Answer every question below to mark this chapter as complete.

Quiz Yourself

Score: 0/4

1. What does calling a useState setter function do?

2. Why use `setCount(prev => prev + 1)` instead of `setCount(count + 1)`?

3. How many times can a component call useState?

4. Why does `items.push(newItem); setItems(items);` fail to trigger a re-render?

You're viewing a free lesson. Sign up free to track your progress and unlock the full course.Sign up freeSign in