跪拜 Guibai
← All articles
React.js

Every React Hook, Catalogued: From useState to Custom Logic Reuse

By 为你学会写情书 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Hooks are the standard React component model now; class components are legacy. Knowing when to use `useLayoutEffect` over `useEffect`, or how `useTransition` keeps typing responsive during expensive renders, directly affects perceived performance and correctness in production React apps.

Summary

React Hooks turn function components into full-featured units that manage state, side effects, and context without classes. Two hard rules govern their use: call them only at the top level of a React function, and never inside loops, conditionals, or plain JavaScript functions. Breaking those rules scrambles the call-order state tracking React depends on.

The guide groups the 13 built-in Hooks into six categories. State Hooks (`useState`, `useReducer`) handle simple and complex state; Context (`useContext`) replaces prop drilling; Ref Hooks (`useRef`, `useImperativeHandle`) hold non-rendering data and limit parent access to child internals; Effect Hooks (`useEffect`, `useLayoutEffect`) synchronize with external systems, with `useLayoutEffect` running synchronously before the browser paints to avoid flicker. Performance Hooks (`useMemo`, `useCallback`) cache values and function references to skip work, though the advice is to reach for them only when a measured problem exists.

React 18 added `useTransition` and `useDeferredValue` for marking non-urgent updates that can be interrupted by urgent ones (like keystrokes), and `useId` for generating stable unique IDs across server and client. The final section demonstrates three custom Hooks — online status, localStorage sync, and debounce — and distills the practice into a rule: when logic repeats across components, extract a Hook whose name begins with `use`.

Takeaways
Hooks must be called unconditionally at the top level of a React function component or custom Hook — never inside loops, conditionals, or plain JS functions.
`useState` supports lazy initialization via a function argument to avoid recomputing the initial value on every render.
`useReducer` suits state logic with multiple sub-values or transitions that depend on the previous state.
`useContext` reads a context value directly, eliminating prop drilling through intermediate components.
Updating a `useRef`'s `.current` property never triggers a re-render; refs are for non-rendering data like DOM nodes or timer IDs.
`useImperativeHandle` paired with `forwardRef` lets a child component expose only specific methods to the parent, hiding its internal DOM structure.
`useEffect` runs asynchronously after paint and is the right choice for most side effects; `useLayoutEffect` runs synchronously before paint and prevents layout flicker.
`useMemo` caches a computed value; `useCallback` caches a function reference. Both should be applied only when profiling shows a real performance bottleneck.
`useTransition` marks a state update as non-urgent so React can keep urgent updates (like input keystrokes) responsive, while `useDeferredValue` defers a value to avoid blocking urgent renders.
`useId` generates stable unique IDs that match between server and client, avoiding hydration mismatches in accessibility attributes.
Custom Hooks must start with `use` and can call other Hooks; they encapsulate reusable stateful logic — online detection, localStorage sync, debounce — that multiple components can share.
Conclusions

The two Hook rules are not stylistic; they exist because React relies on stable call-order indexing to associate state with the correct `useState` or `useEffect` call across renders. Conditional or looped calls break that index.

The guide explicitly warns that `useEffect` is an escape hatch for external-system interaction — a reminder that overusing effects for derived state or synchronization that React can handle declaratively is a common anti-pattern.

`useMemo` and `useCallback` are presented with a caution against premature use, aligning with the React team's own stance that memoization should follow measurement, not habit.

React 18's `useTransition` and `useDeferredValue` represent a meaningful shift in mental model: developers now explicitly categorize updates by urgency, letting the runtime interleave high-priority and low-priority work instead of processing them sequentially.

The custom Hook examples — online status, localStorage, debounce — are small but illustrate the core value proposition: Hooks make stateful behavior a composable unit, not something locked inside a component or a higher-order wrapper.

Concepts & terms
Hook call-order indexing
React tracks Hooks by their call order within a component, not by name or identity. Calling Hooks conditionally or in loops changes the order between renders, causing state to be associated with the wrong Hook call.
useLayoutEffect
A synchronous effect Hook that fires after DOM mutations but before the browser paints. Used for layout measurements that must complete before the user sees a frame, preventing visual flicker.
useTransition
A React 18 Hook that returns an `isPending` flag and a `startTransition` function. Updates wrapped in `startTransition` are marked as non-urgent and can be interrupted by urgent updates like user input.
useDeferredValue
A React 18 Hook that returns a deferred version of a value. React attempts to update the deferred value immediately after the current render, effectively deprioritizing the parts of the UI that depend on it.
Hydration mismatch
A React server-side rendering error where the HTML generated on the server differs from what the client renders on first mount. `useId` helps avoid this by producing IDs that are stable across both environments.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗