DEV Community

Cover image for ๐Ÿš€ React Performance Optimization Tips I Wish I Knew Earlier
Sachin Maurya
Sachin Maurya

Posted on

๐Ÿš€ React Performance Optimization Tips I Wish I Knew Earlier

๐Ÿคฏ Introduction

When I began using React, I was obsessed with making things work โ€” not making them fast. Over time, I noticed lags, unnecessary re-renders, and slow UI. Thatโ€™s when I dove deep into performance and found gold.

In this post, Iโ€™ll share React performance optimization tips I wish I knew earlier, so you can skip the slowdowns and jump straight to building snappy apps.


โš™๏ธ 1. Use React.memo Smartly

React re-renders components even if the props havenโ€™t changed โ€” unless you wrap them in React.memo.

const Button = React.memo(({ onClick, children }) => {
  console.log("Button rendered");
  return <button onClick={onClick}>{children}</button>;
});
Enter fullscreen mode Exit fullscreen mode

โœ… Use it for pure components receiving primitive props.
โŒ Donโ€™t overuse โ€” memo itself has an overhead.


๐Ÿง  2. Optimize with useCallback & useMemo

Prevent unnecessary re-renders or recalculations.

const handleClick = useCallback(() => {
  console.log("Clicked!");
}, []);
Enter fullscreen mode Exit fullscreen mode
const expensiveValue = useMemo(() => {
  return computeHeavyStuff(data);
}, [data]);
Enter fullscreen mode Exit fullscreen mode

These hooks keep references stable and prevent child components from rerendering.


๐Ÿ’ฅ 3. Avoid Inline Functions & Objects in JSX

Inline functions get recreated on every render:

// โŒ Triggers re-renders
<MyComponent onClick={() => doSomething()} />

// โœ… Better with useCallback
const handleClick = useCallback(() => doSomething(), []);
<MyComponent onClick={handleClick} />
Enter fullscreen mode Exit fullscreen mode

Same applies to style={{}} and inline objects.


๐Ÿ“ฆ 4. Code-Splitting with React.lazy & Suspense

Donโ€™t ship your entire app upfront.

const Settings = React.lazy(() => import('./Settings'));

<Suspense fallback={<Loader />}>
  <Settings />
</Suspense>
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“‰ Keeps bundle size small
๐Ÿš€ Faster initial page load


๐Ÿงน 5. Clean Up useEffect Side Effects

Uncleared intervals or subscriptions lead to memory leaks.

useEffect(() => {
  const id = setInterval(doSomething, 1000);
  return () => clearInterval(id);
}, []);
Enter fullscreen mode Exit fullscreen mode

Always clean up effects when using timers, listeners, or subscriptions.


๐Ÿ”„ 6. Avoid Unnecessary Re-renders

Use tools like:

  • why-did-you-render
  • React DevTools Profiler
// Development only
import whyDidYouRender from '@welldone-software/why-did-you-render';

if (process.env.NODE_ENV === 'development') {
  whyDidYouRender(React);
}
Enter fullscreen mode Exit fullscreen mode

These help you see whatโ€™s rerendering and why.


๐Ÿข 7. Virtualize Long Lists

Rendering hundreds of DOM nodes? Thatโ€™s slow.

Use react-window or react-virtualized:

import { FixedSizeList as List } from 'react-window';

<List height={400} itemCount={1000} itemSize={35} width={300}>
  {({ index, style }) => <div style={style}>Item {index}</div>}
</List>
Enter fullscreen mode Exit fullscreen mode

Only renders visible items. Huge performance gain.


๐Ÿงฏ 8. Debounce Expensive Updates

Avoid re-rendering on every keystroke.

const debouncedSearch = useMemo(() => debounce(handleSearch, 300), []);
Enter fullscreen mode Exit fullscreen mode

Use:

  • lodash.debounce
  • use-debounce (React hook)

๐Ÿ’ก 9. Bonus Quick Wins

  • Error Boundaries Prevent the entire UI from crashing:
  class ErrorBoundary extends React.Component {
    state = { hasError: false };
    static getDerivedStateFromError() {
      return { hasError: true };
    }
    render() {
      return this.state.hasError ? <Fallback /> : this.props.children;
    }
  }
Enter fullscreen mode Exit fullscreen mode
  • Skeleton Loaders Improve perceived performance:
  <div className="h-6 w-full bg-gray-300 animate-pulse" />
Enter fullscreen mode Exit fullscreen mode
  • Intersection Observer with useRef Lazy load components only when in view.
  const ref = useRef();
  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        // Trigger load
      }
    });
    if (ref.current) observer.observe(ref.current);
  }, []);
Enter fullscreen mode Exit fullscreen mode

๐ŸŽฏ Final Thoughts

React is powerful, but without understanding how rendering works, itโ€™s easy to make your UI sluggish.

The key is to be intentional: Measure โ†’ Identify โ†’ Optimize.

I hope these tips help you build smoother, faster, and more efficient React apps!

Top comments (0)