---
title: Hooks
description: Use state and lifecycle logic in function components without classes.
tokens: ~853
---

# Hooks

React 16.8 introduced Hooks — functions that let you use state, effects, and other React features inside function components. Before hooks, adding state or lifecycle logic meant converting to a class component, dealing with `this` binding, constructor boilerplate, and wrapper hell from HoCs and render props. Hooks eliminated all of that.

## Built-in Hooks

### State

- `useState` — local state in a function component
- `useReducer` — complex state managed through a reducer function

### Effects

- `useEffect` — run side effects (data fetching, subscriptions, DOM mutations) after render
- `useLayoutEffect` — same as `useEffect` but fires synchronously after DOM mutations, before the browser paints
- `useInsertionEffect` — inject styles before layout reads; meant for CSS-in-JS libraries

### Context

- `useContext` — read a context value without a Consumer wrapper

### Refs

- `useRef` — hold a mutable value that persists across renders (commonly a DOM node)
- `useImperativeHandle` — customize the ref value a parent sees when using `ref`

### Performance

- `useMemo` — memoize an expensive computation so it only recalculates when dependencies change
- `useCallback` — memoize a function reference to avoid unnecessary re-renders of children
- `useTransition` — mark a state update as non-urgent so the UI stays responsive (React 18)
- `useDeferredValue` — defer re-rendering a value until higher-priority updates finish (React 18)

### Identity

- `useId` — generate a stable unique ID for accessibility attributes like `htmlFor`/`id` pairs (React 18)

### Debug

- `useDebugValue` — display a label for custom hooks in React DevTools

### External Stores

- `useSyncExternalStore` — subscribe to an external store with built-in tearing protection (React 18)

### React 19

- `use` — read a Promise or Context; unlike other hooks, it can be called conditionally
- `useActionState` — track the return value and pending state of an async form action
- `useFormStatus` — read the submission status of a parent `<form>` from a child component
- `useOptimistic` — show an optimistic value instantly while an async operation settles

## Custom Hooks

A custom hook is a function whose name starts with `use` and that composes built-in hooks. It lets you extract and share stateful logic between components without adding wrapper layers.

```tsx
function useKeyPress(targetKey: string): boolean {
  const [pressed, setPressed] = useState(false);

  useEffect(() => {
    const down = (e: KeyboardEvent) => {
      if (e.key === targetKey) setPressed(true);
    };
    const up = (e: KeyboardEvent) => {
      if (e.key === targetKey) setPressed(false);
    };

    window.addEventListener("keydown", down);
    window.addEventListener("keyup", up);
    return () => {
      window.removeEventListener("keydown", down);
      window.removeEventListener("keyup", up);
    };
  }, [targetKey]);

  return pressed;
}
```

Any component can call `useKeyPress("Enter")` to react to that key — no HoC or render prop needed.

## Rules of Hooks

1. **Call hooks at the top level only.** No hooks inside loops, conditions, or nested functions. React relies on call order to match state to the right hook.
2. **Call hooks from React functions only.** Either a function component or another custom hook — never a plain JavaScript function.

The `eslint-plugin-react-hooks` plugin enforces both rules at lint time.