React Hooks Cheatsheet: useState, useEffect, useRef, useMemo and useCallback
React hooks without the guesswork: useState and useEffect patterns, when refs beat state, useMemo and useCallback done right, context, reducers, and the rules of hooks.
1. useState and useEffect: The Daily Pair
State triggers re-renders; effects synchronize with things outside React (network, timers, the DOM). Always clean up subscriptions and intervals, and declare every dependency you use.
import { useState, useEffect } from "react";
function UserCard({ userId }) {
const [user, setUser] = useState(null);
const [count, setCount] = useState(0);
// Functional update: safe when the new value depends on the old
const bump = () => setCount(c => c + 1);
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => { if (!cancelled) setUser(data); });
return () => { cancelled = true; }; // cleanup on unmount/re-run
}, [userId]); // re-run when userId changes
if (!user) return <p>Loadingβ¦</p>;
return <button onClick={bump}>{user.name}: {count}</button>;
}
2. useRef, useMemo and useCallback
Reach for these only when you can name the problem they solve: a value that must persist without re-rendering, an expensive computation, or a function identity that a memoized child depends on.
| Hook | Use it for | Remember |
|---|---|---|
useRef(initial) | DOM nodes, timers, previous values | Changing .current never re-renders |
useMemo(() => calc, [deps]) | Expensive derived values | A performance tool, not a correctness tool |
useCallback(fn, [deps]) | Stable function identity for memoized children | Pair it with React.memo on the child |
useId() | Unique ids for form labels and ARIA | Stable across server and client renders |
useTransition() | Mark updates as non-urgent | Keeps the UI responsive during heavy renders |
useDeferredValue(v) | Render a lagging copy of a fast-changing value | Great for search inputs over big lists |
3. useContext and useReducer
Context shares values down the tree without prop drilling (theme, current user, locale). A reducer centralizes state transitions when updates have names and rules.
const ThemeContext = createContext("light");
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
function Toolbar() {
const theme = useContext(ThemeContext);
return <div className={theme}>β¦</div>;
}
// Reducer: one place decides how state changes
function reducer(state, action) {
switch (action.type) {
case "add": return [...state, action.item];
case "remove": return state.filter(i => i.id !== action.id);
default: return state;
}
}
const [items, dispatch] = useReducer(reducer, []);
dispatch({ type: "add", item: newItem });
4. Rules of Hooks and Your First Custom Hook
Hooks only work because React tracks them by call order. Break the order and state silently attaches to the wrong hook.
- Only call hooks at the top level β never inside loops, conditions or nested functions.
- Only call hooks from React functions β components or other custom hooks, never plain JavaScript functions.
- Prefix custom hooks with "use" so the linter can enforce the rules inside them.
- Every value an effect uses belongs in its dependency array β silence the linter by restructuring, not by deleting deps.
// Custom hook: reusable stateful logic, shared by any component
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const onResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
return width;
}
π Associated Learning Path & Monetization Blueprints
React 19 Hooks and State Management Guide
The full guided tour of hooks, server components and state patterns in React 19.
Read Full Guide βLegacy Code Modernization
Modernize legacy front-ends to hooks-based React for business clients.
Read Blueprint βNeed another cheat sheet?
We add new reference guides every week based on community requests.
Request a Cheatsheet β