It's probably not what you think. Most React performance problems I've seen in production have nothing to do with re-renders.
Every time someone complains about React being slow, the Reddit thread fills up with "just use signals" or "memo everything" or "Solid is better." And sometimes those people are right. But in my experience auditing frontend performance at three different companies, the actual bottleneck is almost never what developers assume it is.
Seriously. Before you reach for useMemo, open the Network tab. Most "slow React apps" I've diagnosed are actually slow because they're waterfall-loading data — component renders, fires a fetch, child component renders, fires another fetch, repeat. You feel it as janky UI when it's really just sequential round-trips.
The fix isn't React-specific. Parallel data fetching, prefetching on hover, moving data requirements up the tree — these are architectural choices that happen to make your app feel 10x faster without touching a single component.
I once profiled a dashboard app that was importing all of lodash, moment.js (with all locales), and a full charting library on every page load. The JS bundle was 4.2MB. Users on decent connections were waiting 8 seconds before they could interact with anything.
Use next/dynamic or React.lazy for heavy components. Audit your bundle with @next/bundle-analyzer. Switch from moment to date-fns. These changes moved that app from 4.2MB to 680KB — a 6x reduction — and fixed the "slowness" overnight.
Profile before you optimize. The problem is almost never where you think it is.
Sometimes, yes, it's excessive re-renders. The React DevTools Profiler will show you — you'll see components lighting up red constantly for operations that should be cheap. In those cases, memo, useCallback, and moving state down the tree are the right tools. But reach for them after you've ruled out the network and bundle first. Don't optimize what isn't broken.