A checklist for React/Next.js code, ordered roughly by impact — bundle-size
mistakes tend to cost more than a missed useMemo.
Bundle size (highest impact)
- Avoid importing from barrel files (
import { Button } from "@/components") when the bundler can't statically tree-shake them — import from the specific module instead. - Check whether a heavy dependency has a lighter alternative before adding it; a date library or icon set pulled in for one function can dominate bundle size.
- Code-split anything not needed on first paint (modals, below-the-fold sections, admin-only views) via dynamic import.
Rendering
- Don't create new object/array/function literals inline in JSX props when the child is memoized — it defeats the memoization on every render.
- Lift state only as high as the components that actually need it; state placed too high re-renders siblings that don't care about it.
- Prefer deriving values during render over
useEffect+useStatefor anything computable synchronously from existing props/state.
Data fetching
- Fetch in Server Components by default; only reach for client-side fetching when the data is genuinely interactive/user-specific after load.
- Parallelize independent requests (
Promise.all) instead of sequentialawaits that don't depend on each other. - Cache/revalidate deliberately — an uncached fetch on a high-traffic route is a query-per-request problem waiting to happen.
Hooks
- Every
useEffectneeds a stated reason it can't be derived during render or handled in an event handler instead — effects are for synchronizing with external systems, not general-purpose "run this after render." - Keep dependency arrays honest; suppressing the lint rule instead of fixing the dependency is usually hiding a real bug, not a false positive.
How to use this
Apply during code review or before committing new UI code — not as a retroactive audit of an entire codebase in one pass. Fix the highest-impact category first if forced to choose.