AlgoInsight

Q&A

React Hooks introduction - useState

By AlgoInsight Team2026-06-07frontendreactreact-hooksjavascript

Overview

Before Hooks, only class components could have state. Hooks let function components "hook into" React features. useState is the entry point: it gives a component a piece of state that persists across re-renders and, when changed, causes React to re-render the component with the new value.

graph TD
    A[Component renders] --> B["const [count, setCount] = useState(0)"]
    B --> C[User clicks button]
    C --> D["setCount(count + 1)"]
    D --> E[React schedules re-render]
    E --> A
    style D fill:#1e1b4b,color:#fff

Basic Usage

import { useState } from "react";

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

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

Functional Updates (when new state depends on old)

If the next state depends on the previous state - especially with multiple rapid updates - pass a function to the setter so you always read the latest value:

setCount(prev => prev + 1);   // safe; uses the most recent state

This avoids stale-state bugs that arise because state updates are asynchronous and may be batched.

State with Objects and Arrays

State updates replace, they don't merge. With objects/arrays, create a new copy (immutability):

const [user, setUser] = useState({ name: "Ada", age: 30 });
setUser(prev => ({ ...prev, age: 31 }));     // spread to keep other fields

const [items, setItems] = useState([]);
setItems(prev => [...prev, newItem]);        // new array, don't mutate

Mutating state directly (user.age = 31) won't trigger a re-render and breaks React's model.

Lazy Initialization

If the initial value is expensive to compute, pass a function - React calls it only on the first render:

const [data, setData] = useState(() => expensiveComputation());

Rules of Hooks

  1. Only call Hooks at the top level - never inside loops, conditions, or nested functions. React relies on call order to track state across renders.
  2. Only call Hooks from React function components or custom Hooks - not regular functions.
// WRONG - conditional Hook
if (loggedIn) { const [x, setX] = useState(0); }
// RIGHT - top level, then branch on the value
const [x, setX] = useState(0);
if (loggedIn) { /* use x */ }

Multiple State Variables

Use useState as many times as you need; keep unrelated state separate:

const [name, setName] = useState("");
const [age, setAge]   = useState(0);
const [open, setOpen] = useState(false);

Why This Matters in Interviews

React interviews almost always cover useState. Know that it returns a [value, setter] pair, that updates are asynchronous/batched (hence functional updates), that state must be treated immutably, and the Rules of Hooks (top-level only, and why - React tracks Hooks by call order). Distinguishing setCount(count+1) from setCount(c => c+1) is a classic discriminator.

Common Pitfalls

References

More answers