useState
Purpose: Store and change data. Updates component when data changes.
const [count, setCount] = useState(0);
setCount(count + 1);
Use: Any changing data in component.
useEffect
Purpose: Run code after component renders. For API calls, timers, subscriptions.
useEffect(() => {
fetchData();
}, [dependency]); // Run when dependency changes
Use: API calls, side effects, cleanup.
useContext
Purpose: Share data across many components without prop drilling.
const theme = useContext(ThemeContext);
Use: Global data like theme, user auth, language.
useReducer
Purpose: Complex state with multiple updates. Like a mini database.
const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: 'ACTION_NAME' });
Use: Forms with many fields, list management, complex logic.
useRef
Purpose: Direct access to DOM or store values without re-render.
const inputRef = useRef();
inputRef.current.focus();
Use: Focus elements, store timers, DOM measurements.
useMemo
Purpose: Cache calculation results to avoid recalculation.
const result = useMemo(() => expensiveCalculation(), [dependency]);
Use: Heavy calculations, performance optimization.
useCallback
Purpose: Cache function to keep same reference across renders.
const handleClick = useCallback(() => doSomething(), [dependency]);
Use: Pass functions to child components, dependencies in hooks.
useId
Purpose: Generate unique IDs for form elements.
const id = useId();
<input id={id} />
Use: Accessible forms, unique identifiers.
useLayoutEffect
Purpose: Run code before browser paints (before useEffect).
useLayoutEffect(() => {
const width = element.offsetWidth;
}, []);
Use: DOM measurements, animations (rarely needed).
Key Rules
- Call hooks only at top level (not in loops/conditions)
- Only use in functional components
- Hook names start with “use”