useState Hook

useState Hook

useState lets you add state to a function component. It returns a pair: the current state value and a function to update it.

Syntax

const [state, setState] = useState(initialValue);

// initialValue can be a value OR a function (lazy initialisation)
const [expensive, setExpensive] = useState(() => computeExpensiveDefault());

All State Types

// String
const [name, setName]     = useState("");

// Number
const [count, setCount]   = useState(0);

// Boolean
const [isOpen, setIsOpen] = useState(false);

// Array
const [items, setItems]   = useState([]);

// Object
const [user, setUser]     = useState({ name: "", email: "" });

// null (data not yet loaded)
const [data, setData]     = useState(null);

Functional Updates โ€” The Safe Pattern

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

  // โŒ Can produce stale state in async contexts
  const incrementBad  = () => setCount(count + 1);

  // โœ… Always correct โ€” prev is guaranteed to be current
  const incrementGood = () => setCount(prev => prev + 1);

  // Multiple updates in one event โ€” without functional form only ONE update runs
  const incrementThrice = () => {
    setCount(prev => prev + 1); // โœ…
    setCount(prev => prev + 1); // โœ…
    setCount(prev => prev + 1); // โœ…
    // Final count = prev + 3
  };
}

Complex State Example โ€” Shopping Cart

function ShoppingCart() {
  const [cart, setCart] = useState([]);

  const addItem = (product) => setCart(prev => {
    const exists = prev.find(i => i.id === product.id);
    if (exists) {
      return prev.map(i => i.id === product.id ? { ...i, qty: i.qty + 1 } : i);
    }
    return [...prev, { ...product, qty: 1 }];
  });

  const removeItem = (id) =>
    setCart(prev => prev.filter(i => i.id !== id));

  const totalPrice = cart.reduce((sum, i) => sum + i.price * i.qty, 0);

  return (
    <div>
      <h2>Cart ({cart.length} items) โ€” ${totalPrice.toFixed(2)}</h2>
      {cart.map(item => (
        <div key={item.id}>
          {item.name} ร— {item.qty}
          <button onClick={() => removeItem(item.id)}>Remove</button>
        </div>
      ))}
    </div>
  );
}

๐Ÿง  Test Yourself

What does useState return?