8/10 lessons80%

Performance Optimization: Stop Re-rendering Everything

Performance in React is a weird beast. You don’t notice it until your app turns into molasses. I once built a dashboard with a few innocent-looking charts. It ran fine… until someone opened it on a 2015 MacBook and the fan sounded like a rocket launch. That was my wake-up call. React gives you tools like useMemo, useCallback, and code splitting to avoid this exact fate—but like any tool, you’ve got to know when to use them, and more importantly, when not to.

What to Optimize (And What Not To)

Here’s the golden rule: Don’t optimize everything. Optimize what’s slow.

You’d be surprised how many devs reach for useMemo like it’s seasoning. Sprinkle it everywhere and hope the app runs faster. News flash—it won’t. Sometimes it even slows things down.

Start by measuring. Use the React DevTools Profiler or even the built-in browser performance tab. Figure out what’s actually re-rendering too much or taking forever to paint. Are your components re-rendering because props keep changing? Are you re-fetching data that never changes?

If the answer is “it feels slow but I haven’t measured,” don’t touch anything yet. Guessing is the enemy of good performance.

useMemo vs useCallback: Which One Saves the Day?

Both of these hooks are about memoization—keeping React from recalculating things unnecessarily.

`useMemo` is for expensive calculations*.

javascript
1
            const sortedList = useMemo(() => sort(data), [data]);
        

Think: sorting large arrays, filtering data, crunching numbers.

`useCallback` is for functions* you don’t want to re-create on every render.

javascript
1
            const handleClick = useCallback(() => doSomething(id), [id]);
        

This is huge when passing callbacks to memoized child components. Without useCallback, the child sees a new function on every render—and re-renders itself. Ouch.

Personal tip? Don’t wrap everything in useCallback. You’ll end up with clutter and no real benefit. But for components wrapped in React.memo, it’s worth it.

If you want more nuance, Kent C. Dodds’ explanation cuts through the fluff.

Lazy Loading and Code Splitting: Your Secret Weapons

Modern React is all about shaving off load times. Enter: React.lazy and Suspense.

Let’s say you’ve got a huge component like a chart or a modal that’s not always visible. You can load it only when needed:

javascript
1
2
3
4
5
          const Chart = React.lazy(() => import('./Chart'));

<Suspense fallback={<Loading />}>
  <Chart />
</Suspense>
        

This reduces your initial bundle size—which means faster load times and happier users. And yes, Google likes fast sites, so it’s also good for SEO.

I once cut load time by half on a client’s ecommerce dashboard just by lazy loading three analytics widgets. No rewrites. Just smarter imports.

You can also take it further with tools like Webpack’s code splitting or route-level splitting with React Router.

Now that your app isn't choking on every render or loading every component on day one, you're ready to make sure your code actually works. And that’s where we go next: Testing React Components.