Cheatsheet for React 19 Hooks
few minutes
reactjs
cheatsheetreactjs
Beginner
developer

State Hooks

useState

  • Adds local state to a component.
  • State updates trigger re-render.
  • Setter accepts:
    • Direct value
    • Updater function
  • Updates are async and batched.
const [count, setCount] = useState(0);

setCount(count + 1);

setCount(prev => prev + 1);

useReducer

  • Alternative to useState for complex logic.
  • Centralizes updates in reducer function.
  • Good for nested state and state machines.
type Action =
  | { type: 'inc' }
  | { type: 'dec' };

function reducer(state: number, action: Action) {
  switch (action.type) {
    case 'inc':
      return state + 1;
    case 'dec':
      return state - 1;
    default:
      return state;
  }
}

const [count, dispatch] = useReducer(reducer, 0);

dispatch({ type: 'inc' });

Effect Hooks

useEffect

  • Runs side effects after render.
  • Used for:
    • Fetching
    • Timers
    • Subscriptions
    • DOM sync
  • Cleanup runs:
    • Before next effect
    • On unmount
useEffect(() => {
  const id = setInterval(() => {
    console.log('tick');
  }, 1000);

  return () => clearInterval(id);
}, []);

Dependencies

useEffect(() => {}, []);        // once
useEffect(() => {}, [value]);  // when value changes
useEffect(() => {});           // every render

Abort Fetch

useEffect(() => {
  const controller = new AbortController();

  fetch('/api/data', {
    signal: controller.signal
  });

  return () => controller.abort();
}, []);

useLayoutEffect

  • Like useEffect but runs:
    • Synchronously
    • Before browser paint
  • Use for layout measurement.
  • Blocks paint → use sparingly.
useLayoutEffect(() => {
  const height = ref.current?.offsetHeight;
  console.log(height);
}, []);

useInsertionEffect

  • Runs before DOM mutations.
  • Mainly for CSS-in-JS libraries.
  • Rare in application code.
useInsertionEffect(() => {
  // inject styles
}, []);

Ref Hooks

useRef

  • Stores mutable value without re-render.
  • Common uses:
    • DOM refs
    • Timer IDs
    • Previous values
    • Instance variables
const inputRef = useRef<HTMLInputElement>(null);

inputRef.current?.focus();

Mutable Storage

const countRef = useRef(0);

countRef.current++;

useImperativeHandle

  • Customizes exposed ref API.
  • Usually used with forwardRef.
type InputHandle = {
  focus: () => void;
};

const CustomInput = forwardRef<InputHandle>((props, ref) => {
  const inputRef = useRef<HTMLInputElement>(null);

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current?.focus();
    }
  }));

  return <input ref={inputRef} />;
});

Context Hooks

useContext

  • Reads nearest context value.
  • Re-renders when context changes.
const ThemeContext = createContext('light');

const theme = useContext(ThemeContext);

Provider

<ThemeContext.Provider value="dark">
  <App />
</ThemeContext.Provider>

Performance Hooks

useMemo

  • Memoizes computed value.
  • Avoids expensive recalculation.
  • Optimization hint only.
const sorted = useMemo(() => {
  return items.sort(compare);
}, [items]);

useCallback

  • Memoizes function reference.
  • Useful for:
    • Stable props
    • Dependency arrays
    • Preventing child re-renders
const handleClick = useCallback(() => {
  console.log('clicked');
}, []);

Equivalent

useMemo(() => fn, deps);

memo

  • Memoized component.
  • Skips re-render if props unchanged.
const Child = memo(function Child({ value }) {
  return <div>{value}</div>;
});

Custom Comparison

memo(Component, (prev, next) => {
  return prev.id === next.id;
});

Concurrent / Scheduling Hooks

useTransition

  • Marks updates as non-urgent.
  • Keeps UI responsive during heavy renders.
const [isPending, startTransition] = useTransition();

startTransition(() => {
  setSearch(query);
});

Good For

  • Filtering
  • Navigation
  • Large lists

useDeferredValue

  • Defers updating a value.
  • Helps avoid laggy UI.
const deferredQuery = useDeferredValue(query);

Common Uses

  • Search
  • Filtering

ID Hook

useId

  • Generates stable unique IDs.
  • Safe for SSR + hydration.
const id = useId();

<label htmlFor={id}>Name</label>
<input id={id} />

External Store Hook

useSyncExternalStore

  • Subscribes to external stores safely.
  • Prevents tearing in concurrent rendering.
const value = useSyncExternalStore(
  store.subscribe,
  store.getSnapshot
);

Used By

  • Redux
  • Zustand
  • Custom stores

React 19 Hooks

use

  • Reads:
    • Promises
    • Context
    • Resources
  • Suspends while waiting.

Promise Example

const data = use(fetchData());

Context Example

const theme = use(ThemeContext);

Works In

  • Server Components
  • Client Components

useActionState

  • Manages async action state.
  • Common with forms and server actions.
const [state, formAction, pending] =
  useActionState(async (prevState, formData) => {
    return {
      success: true
    };
  }, initialState);

Form Usage

<form action={formAction}>
  <button disabled={pending}>
    Submit
  </button>
</form>

useOptimistic

  • Optimistic UI updates before server confirmation.
const [optimisticTodos, addOptimisticTodo] =
  useOptimistic(todos, (state, newTodo) => [
    ...state,
    newTodo
  ]);

Usage

addOptimisticTodo(todo);

Good For

  • Chat
  • Likes
  • Comments

useFormStatus

  • Reads parent form submission status.
  • Must be inside form subtree.
const { pending } = useFormStatus();

<button disabled={pending}>
  Submit
</button>

Useful With

  • Server actions
  • Progressive enhancement

Custom Hooks

Rules

  • Must start with use.
  • Can call other hooks.
  • Reuse stateful logic.
function useCounter() {
  const [count, setCount] = useState(0);

  const inc = () => setCount(c => c + 1);

  return { count, inc };
}

Usage

const { count, inc } = useCounter();

Rules of Hooks

Only Call Hooks

  • At top level.
  • Inside React components.
  • Inside custom hooks.

❌ Invalid

if (condition) {
  useEffect(() => {});
}

✅ Valid

useEffect(() => {
  if (condition) {
    // logic
  }
}, [condition]);

Common Patterns

Previous Value

function usePrevious<T>(value: T) {
  const ref = useRef<T>();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

Stable Event Callback

const onClick = useCallback(() => {
  doSomething(id);
}, [id]);

Fetch Pattern

useEffect(() => {
  let ignore = false;

  async function load() {
    const res = await fetch('/api/data');
    const data = await res.json();

    if (!ignore) {
      setData(data);
    }
  }

  load();

  return () => {
    ignore = true;
  };
}, []);

Hooks Decision Guide

NeedHook
Local stateuseState
Complex stateuseReducer
Side effectsuseEffect
DOM accessuseRef
Shared stateuseContext
Expensive computationuseMemo
Stable callbackuseCallback
Non-blocking updateuseTransition
Deferred renderinguseDeferredValue
External storeuseSyncExternalStore
Async resource readinguse
Optimistic updatesuseOptimistic
Form action stateuseActionState
Form pending statususeFormStatus