React Hooks
useState, useEffect, useMemo, useCallback, useRef, useReducer, useContext
Essential Hooks
tsx
// Hook Patterns
import { useState, useEffect, useMemo, useCallback, useRef, useReducer, useContext, createContext } from "react";
// useState — simple state
const [query, setQuery] = useState("");
// useEffect — side effects (API calls, subscriptions, DOM)
useEffect(() => {
const controller = new AbortController();
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then(r => r.json())
.then(setResults);
return () => controller.abort(); // cleanup
}, [query]); // re-run when query changes
// useRef — persist value without re-render
const inputRef = useRef<HTMLInputElement>(null);
const renderCount = useRef(0);
useEffect(() => { renderCount.current++; });
// inputRef.current?.focus()
// useMemo — memoize expensive computation
const sorted = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
// useCallback — memoize function reference
const handleSubmit = useCallback((data: FormData) => {
api.submit(data);
}, []);
// useReducer — complex state logic
type Action = { type: "increment" } | { type: "decrement" } | { type: "reset" };
function reducer(state: number, action: Action) {
switch (action.type) {
case "increment": return state + 1;
case "decrement": return state - 1;
case "reset": return 0;
}
}
const [count, dispatch] = useReducer(reducer, 0);
// useContext — global state without prop drilling
const ThemeContext = createContext<"light" | "dark">("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<DeepChild />
</ThemeContext.Provider>
);
}
function DeepChild() {
const theme = useContext(ThemeContext); // "dark"
}Hook Rules
- Only call hooks at the top level — never inside loops, conditions, or nested functions
- Only call hooks from React components or custom hooks
- Custom hooks must start with 'use' prefix
- Dependencies array: [] = run once, [dep] = run when dep changes, no array = every render
💬 When to use useMemo vs useCallback?
useMemo memoizes a computed value (e.g., filtered/sorted list). useCallback memoizes a function reference. Use useCallback when passing functions to child components to prevent unnecessary re-renders. Both take a dependency array.