Performance problems in React apps come in three distinct flavors — and most developers treat them all the same way.
Network performance is about how much JavaScript the user has to download before anything happens. A 3MB bundle on a 4G connection takes 6+ seconds. The user hasn't even started rendering yet.
Render performance is about wasted React work. One state change at the top of your tree can trigger hundreds of unnecessary re-renders — and the user feels it as choppy interactions, janky typing, and sluggish filters.
Perceived performance is about psychology. A page that shows something in 100ms and fills in over the next 800ms feels faster than a page that shows nothing for 900ms, even if the total time is identical. Streaming and skeletons exploit this.
The trap
memo() everywhere, split every component into its own chunk, and virtualize every list — before checking if these are actually the bottlenecks. The result: added complexity, no measurable improvement.