React Hooks Reference
Complete reference for all built-in React hooks — useState, useEffect, useContext, and more.
React hooks let you use state and other React features in function components. They must be called at the top level of a component — never inside loops, conditions, or nested functions.
useState
Adds local state to a function component.
const [state, setState] = useState(initialValue);
// With a lazy initializer (computed once)
const [data, setData] = useState(() => expensiveComputation());
// Updating based on previous state
setCount(prev => prev + 1);
| Concept | Description |
|---|---|
| Initial value | Used on first render; can be any type or a function returning the initial value |
| Setter function | setState triggers a re-render; pass a value or a function receiving the previous state |
| Shallow merge | Unlike class setState, the setter replaces the value — it does not merge objects |
| Batching | React 18 batches all state updates automatically, even in timeouts and promises |
useEffect
Runs side effects after render. The dependency array controls when it re-runs.
// Run after every render
useEffect(() => {
console.log("rendered");
});
// Run once on mount
useEffect(() => {
console.log("mounted");
}, []);
// Run when dependencies change
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
// Cleanup on unmount
useEffect(() => {
const subscription = subscribe();
return () => subscription.unsubscribe();
}, []);
| Concept | Description |
|---|---|
| No deps | Runs after every render |
Empty deps [] |
Runs once on mount; cleanup runs on unmount |
Dep list [a, b] |
Runs when any dependency changes |
| Cleanup return | Optional function returned runs before the next effect and on unmount |
useContext
Reads context value from the nearest provider. Avoids prop drilling.
const ThemeContext = createContext<"light" | "dark">("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
}
| Concept | Description |
|---|---|
| Provider | Context.Provider wraps children and supplies the value |
| Consumer | useContext(Context) reads the nearest provider’s value |
| Default value | Used when no provider is found above in the tree |
| Re-render | All consumers re-render when the provider value changes |
useReducer
An alternative to useState for complex state logic.
interface State {
count: number;
}
type Action = { type: "increment" } | { type: "decrement" } | { type: "reset" };
function reducer(state: State, action: Action): State {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "decrement": return { count: state.count - 1 };
case "reset": return { count: 0 };
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
dispatch({ type: "increment" });
useRef
Creates a mutable reference that persists across renders without causing re-renders.
// DOM reference
const inputRef = useRef<HTMLInputElement>(null);
<input ref={inputRef} />;
inputRef.current?.focus();
// Mutable value (not for rendering)
const timerRef = useRef<number>();
timerRef.current = window.setInterval(() => {}, 1000);
useMemo
Memoizes an expensive computation. Only recalculates when dependencies change.
const sortedItems = useMemo(() => {
return items.toSorted((a, b) => a.name.localeCompare(b.name));
}, [items]);
useCallback
Returns a memoized function reference. Useful when passing callbacks to optimized child components.
const handleClick = useCallback((id: string) => {
selectItem(id);
}, [selectItem]);
useLayoutEffect
Fires synchronously after all DOM mutations. Use for measuring layout or synchronously updating the DOM.
useLayoutEffect(() => {
const height = ref.current?.offsetHeight ?? 0;
setTooltipPosition(height + 8);
}, [ref]);
useId
Generates unique IDs for accessibility attributes. Guaranteed to be stable across server and client.
const id = useId();
<label htmlFor={id}>Name</label>
<input id={id} />;
Custom Hooks
Extract reusable logic into a custom hook. Name must start with use.
function useDebounce<T>(value: T, delay: number): T {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
// Usage
const searchTerm = useDebounce(inputValue, 300);