React Hooks transformed how developers write components. Introduced in React 16.8, hooks let you use state and other React features without writing a class. Since then, the hooks API has expanded to cover state management, side effects, context sharing, performance optimization, form handling, and external store synchronization. For developers working with React daily — whether building single-page applications, design systems, or server-rendered apps — having a quick reference for every hook and its proper usage saves hours of documentation diving.
Our free interactive React Hooks cheat sheet organizes every built-in hook into nine clear categories, from foundational state hooks to the new React 19 form action hooks. Each entry includes a concise description, a production-ready code example with syntax highlighting, and relevant tags. You can filter by category, search by keyword, and copy any code snippet to your clipboard with one click. The entire tool runs in your browser with no server interaction.
Why Developers Need a React Hooks Cheat Sheet
React ships with over twenty built-in hooks, and the custom hooks ecosystem adds hundreds more patterns developers reuse across projects. Even experienced React engineers occasionally need to check the exact signature of useSyncExternalStore, remember whether useLayoutEffect fires before or after paint, or verify the rules for dependency arrays in useEffect.
The real value of a cheat sheet is cognitive offloading. Rather than holding every hook signature in working memory, you can keep a reference open and focus on solving the actual problem. Our interactive format goes further — search for "debounce" and you will find both the built-in hooks that support debouncing patterns and the custom hook implementation. Filter by "Performance" and every optimization hook appears instantly.
What This Cheat Sheet Covers
Our React Hooks reference is organized into nine categories that map to real development workflows:
- State Management — useState and useReducer for local component state.
- Effects — useEffect, useLayoutEffect, and useInsertionEffect for side effects and lifecycle management.
- Context — useContext for sharing data across component trees without prop drilling.
- Refs & DOM — useRef and useImperativeHandle for direct DOM access and parent-child imperative APIs.
- Performance — useMemo, useCallback, useTransition, and useDeferredValue for optimizing renders and keeping the UI responsive.
- Identity & Debug — useId and useDebugValue for accessibility IDs and DevTools labeling.
- External Store — useSyncExternalStore for subscribing to external mutable data sources.
- Forms & Actions — React 19 hooks: useActionState, useOptimistic, and useFormStatus for modern form handling.
- Custom Hooks — Ten reusable patterns every React developer should know, from useLocalStorage to useDebounce.
The Rules of Hooks
Before diving into individual hooks, every React developer must internalize the Rules of Hooks. These are not guidelines — they are hard constraints that React enforces through its ESLint plugin. Violating them causes unpredictable behavior.
First, only call hooks at the top level of your function component or custom hook. Never call hooks inside loops, conditions, or nested functions. React relies on the call order to match hooks with their internal state.
Second, only call hooks from React function components or custom hooks. Never call them from regular JavaScript functions, class components, or event handlers directly.
Third, custom hooks must start with use so React's linter can enforce the rules. This naming convention is mandatory, not stylistic.
State Management Hooks
useState
useState is the most fundamental hook. It returns a stateful value and a function to update it. When you call the updater, React schedules a re-render with the new state.
const [count, setCount] = useState(0);
// Functional update — preferred when new state depends on previous
setCount(prev => prev + 1);
// Lazy initialization — function runs only on first render
const [data, setData] = useState(() => expensiveComputation()); The functional update form is critical when the new state depends on the previous value. Without it, stale closures can cause bugs in async callbacks. Lazy initialization avoids running expensive setup logic on every render.
useReducer
useReducer is ideal for complex state logic involving multiple sub-values or when the next state depends on the previous one. It follows the same reducer pattern as Redux but operates locally within a component.
const [state, dispatch] = useReducer(reducer, initialState);
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
default:
return state;
}
}
dispatch({ type: 'increment' }); Use useReducer when state updates are complex, when the next state depends on multiple previous values, or when you want to colocate update logic with the state it modifies.
Effect Hooks
useEffect
useEffect handles side effects after React commits changes to the DOM. It accepts a setup function and an optional dependency array. The setup function can return a cleanup function that runs before the effect re-runs or when the component unmounts.
useEffect(() => {
const connection = createConnection(serverUrl);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl]); The dependency array controls when the effect runs. An empty array [] means run once on mount. Omitting the array means run after every render. Including values means run when those values change. Always include every reactive value used inside the effect.
useLayoutEffect
useLayoutEffect fires synchronously after all DOM mutations but before the browser paints. Use it when you need to measure DOM elements and synchronously re-render before the user sees the layout. In most cases, prefer useEffect.
useLayoutEffect(() => {
const width = ref.current.getBoundingClientRect().width;
setTooltipPosition(width);
}, []); useInsertionEffect
useInsertionEffect fires before useLayoutEffect and before React makes DOM changes. It exists primarily for CSS-in-JS libraries to inject styles before any layout effects read the DOM. Application code rarely needs this hook.
Context Hook
useContext
useContext accepts a context object created by createContext and returns the current context value. The component re-renders whenever the context value changes. Context solves prop drilling but should not replace all state management.
const ThemeContext = createContext('light');
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>Click</button>;
} Context is best for low-frequency updates like themes, locales, and authenticated user data. For high-frequency updates, consider external state libraries or prop passing.
Refs and DOM Hooks
useRef
useRef returns a mutable ref object whose .current property persists for the full lifetime of the component. Changing .current does not trigger a re-render. It is the primary tool for accessing DOM nodes and storing mutable values that do not affect rendering.
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
<input ref={inputRef} /> useImperativeHandle
useImperativeHandle customizes the instance value exposed to parent components through ref. Use it with forwardRef to expose a focused API instead of the entire DOM node.
const FancyInput = forwardRef(function (props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus() { inputRef.current.focus(); },
scrollIntoView() { inputRef.current.scrollIntoView(); },
}));
return <input ref={inputRef} />;
}); Performance Hooks
useMemo
useMemo returns a memoized value. The function runs during rendering and must be pure. React recalculates the value only when dependencies change. Use it for expensive computations, not as a semantic guarantee.
const sortedList = useMemo(() => {
return [...list].sort((a, b) => b.score - a.score);
}, [list]); useCallback
useCallback returns a memoized callback function. The function reference stays stable between renders unless dependencies change. Essential when passing callbacks to optimized child components wrapped in React.memo.
const handleSubmit = useCallback((data) => {
sendToServer(data, userId);
}, [userId]); useTransition
useTransition, introduced in React 18, lets you mark a state update as non-urgent. React keeps the UI responsive by rendering the current state while preparing the new state in the background. Returns an isPending flag and a startTransition function.
const [isPending, startTransition] = useTransition();
function handleChange(e) {
setInputValue(e.target.value); // urgent
startTransition(() => {
setFilteredList(filterList(e.target.value)); // non-urgent
});
} useDeferredValue
useDeferredValue returns a deferred version of a value that lags behind the original. Useful when a part of your UI is slow to re-render and you want to keep it responsive. Similar to debouncing but integrated with React's rendering schedule.
const deferredQuery = useDeferredValue(query);
// Fast UI uses query directly
<SearchInput value={query} onChange={setQuery} />
// Slow list uses deferredQuery
<SlowSearchResults query={deferredQuery} /> Identity and Debug Hooks
useId
useId, introduced in React 18, generates a unique ID stable across server and client renders. Essential for accessibility attributes like aria-labelledby and htmlFor that must match during hydration.
const id = useId();
<>
<label htmlFor={id}>Name</label>
<input id={id} type="text" />
</> useDebugValue
useDebugValue displays a label for custom hooks in React DevTools. Accepts a formatting function as the second argument to avoid expensive computations when DevTools are closed.
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useDebugValue(isOnline, status => status ? 'Online' : 'Offline');
return isOnline;
} External Store Hook
useSyncExternalStore
useSyncExternalStore, introduced in React 18, subscribes to an external mutable data store in a way compatible with concurrent rendering. Required for state management libraries that read from external sources.
const width = useSyncExternalStore(
(callback) => {
window.addEventListener('resize', callback);
return () => window.removeEventListener('resize', callback);
},
() => window.innerWidth,
() => 1024 // server snapshot
); React 19 Form and Action Hooks
React 19 introduces three new hooks for modern form handling: useActionState, useOptimistic, and useFormStatus. These hooks simplify async form submissions, optimistic UI updates, and form status tracking without manual state management.
useActionState
useActionState manages state for form actions. It returns the current state, a dispatch function, and a pending flag. The action function receives the previous state and form data.
const [state, formAction, isPending] = useActionState(
async (prevState, formData) => {
const email = formData.get('email');
const result = await subscribe(email);
return result;
},
null
); useOptimistic
useOptimistic allows you to show a different state while an async action is in progress. The optimistic state automatically reverts when the action completes or errors.
const [optimisticState, addOptimistic] = useOptimistic(
state,
(currentState, newItem) => [...currentState, { ...newItem, sending: true }]
);
async function sendMessage(formData) {
const text = formData.get('text');
addOptimistic({ text });
await api.sendMessage(text);
} useFormStatus
useFormStatus provides status information about the parent form submission. Must be used inside a component rendered within a form. Returns pending, data, method, and action fields.
function SubmitButton() {
const { pending } = useFormStatus();
return <button disabled={pending}>
{pending ? 'Submitting...' : 'Submit'}
</button>;
} Custom Hooks Patterns
Custom hooks are JavaScript functions that start with use and call other hooks. They let you extract component logic into reusable functions. Here are ten patterns every React developer should know.
useLocalStorage
Persists state to localStorage with automatic JSON serialization and error handling.
function useLocalStorage(key, initialValue) {
const [stored, setStored] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch { return initialValue; }
});
const setValue = useCallback((value) => {
const valueToStore = value instanceof Function ? value(stored) : value;
setStored(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}, [key, stored]);
return [stored, setValue];
} useFetch
Data fetching with loading, error, and data states. Handles cleanup on unmount to prevent state updates on unmounted components.
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
setLoading(true);
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(err => { if (err.name !== 'AbortError') setError(err); })
.finally(() => setLoading(false));
return () => controller.abort();
}, [url]);
return { data, loading, error };
} useDebounce
Delays updating a value until a specified delay has passed since the last change. Perfect for search inputs and auto-save.
function useDebounce(value, delay = 500) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
} useOnClickOutside
Detects clicks outside a referenced element. Used for dropdowns, modals, and popovers.
function useOnClickOutside(ref, handler) {
useEffect(() => {
const listener = (event) => {
if (!ref.current || ref.current.contains(event.target)) return;
handler(event);
};
document.addEventListener('mousedown', listener);
document.addEventListener('touchstart', listener);
return () => {
document.removeEventListener('mousedown', listener);
document.removeEventListener('touchstart', listener);
};
}, [ref, handler]);
} useMediaQuery
Tracks whether a CSS media query matches the current viewport. Enables responsive design in JavaScript.
function useMediaQuery(query) {
const [matches, setMatches] = useState(false);
useEffect(() => {
const mql = window.matchMedia(query);
const listener = (e) => setMatches(e.matches);
setMatches(mql.matches);
mql.addEventListener('change', listener);
return () => mql.removeEventListener('change', listener);
}, [query]);
return matches;
} How to Use the Interactive Cheat Sheet
Our React Hooks Cheat Sheet is designed for zero-friction reference. Open it alongside your IDE and use the search bar to find any hook instantly. The category tabs filter hooks by purpose — State, Effects, Context, Refs, Performance, Identity, External Store, Forms, or Custom. Each card shows the hook name, React version, description, a syntax-highlighted code example, and related tags. Click the Copy button on any code block to copy clean code to your clipboard.
The Quantum Mechanics Lab aesthetic uses a deep space background with animated quantum particle connections, category-colored glowing borders, and a futuristic typography system. It is distinctive, memorable, and easy on the eyes during long coding sessions.
Related Tools and References
Mastering React hooks is just one part of the modern frontend stack. Explore these related tools to round out your development workflow:
- JavaScript Array Methods Cheat Sheet — Every array method with mutating vs non-mutating badges and ES version tags.
- CSS Selectors Cheat Sheet — 70+ selectors with specificity scores and browser support.
- Terminal Commands Cheat Sheet — 80+ Bash, Linux, and macOS commands across 8 categories.
- Git Commands Cheat Sheet — 100+ Git commands for version control workflows.
- Docker Commands Cheat Sheet — 90+ Docker commands for container management.
- Regex Tester — Test regular expressions with live match highlighting.
- JSON Formatter & Validator — Format and validate JSON with error reporting.
- CSS Animation Generator — Build keyframes and transitions visually.
- HTML Formatter & Validator — Format and lint HTML markup.
- Node.js Built-in Modules Cheat Sheet — 70+ Node.js APIs across fs, path, http, events, stream, buffer, crypto, os, and more.
Conclusion
React Hooks have become the standard way to write React components. From the foundational useState and useEffect to the advanced concurrent features in React 18 and the form action hooks in React 19, understanding the full hooks API makes you a more effective React developer. Our interactive cheat sheet puts every hook at your fingertips with production-ready examples you can copy and adapt immediately. Bookmark it, share it with your team, and keep building.