Derive values instead of syncing state
Copying props or other state into useState and keeping it in sync with useEffect causes an extra render and stale values. If something can be computed from what you already have, compute it during render.
Subscribe to the smallest slice of a store
Reading a whole Zustand store re-renders the component on every change — including keystrokes. Select only what you render; use useShallow when you need several fields at once.
Memoize on purpose
useMemofor genuinely expensive work (parsing, tokenizing, large filters) — not for every value.memo()for components that receive stable props but sit under a frequently re-rendering parent.useCallbackonly when the function is a dependency of an effect or a prop of a memoized child.- Measure with the React DevTools Profiler before and after.
Load heavy code on demand
Editors, charts and 3D scenes can weigh hundreds of kilobytes. next/dynamic splits them into their own chunk and renders a placeholder meanwhile.
Lists and keys
Use stable, unique ids as keys. Array indexes are only safe for lists that never reorder, filter or insert; otherwise React reuses the wrong DOM nodes and state.
For thousands of rows, paginate or virtualize (for example with @tanstack/react-virtual) so the DOM only contains what is on screen.