DEV Community

Cover image for How to Make Your React App Faster: 6 Performance Tips and Best Practices
Hardik Gohil
Hardik Gohil

Posted on

How to Make Your React App Faster: 6 Performance Tips and Best Practices

Ah, React! Our beloved library for building UIs. It’s the magic potion that makes our web apps feel interactive and fast—until one day, it doesn’t. Suddenly, you notice things slowing down. Clicking a button feels like sending a letter by carrier pigeon. Your app goes from lightning-fast to coffee-break slow, and users start giving you "the look."

But don’t worry! Just like coffee can fix most of life’s problems (or so we’d like to think), a few key techniques can turbocharge your React app and bring it back to top speed. Let’s explore 6 simple ways to optimize your React app, so it’s faster than your daily caffeine boost.

1. Code-Splitting: Loading Only What You Need

Ever walked into a room, turned on all the lights, and then realized you only needed one? That’s what your React app does when you bundle everything into one big chunk. Instead, with code-splitting, you only load the parts of your app that are needed at the moment. It’s like turning on lights room by room!

Using React.lazy() and Suspenseis a perfect way to implement this:

import React, { Suspense } from 'react';

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

const App = () => {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why it helps: Code-splitting reduces your app's initial load time by deferring loading of unused code until necessary. Users won't have to wait for the whole app to load before seeing something on the screen.

2. Lazy Loading Images: Don’t Load All the Snacks at Once

Imagine ordering a pizza and receiving a year’s worth of groceries instead. Sounds ridiculous, right? Well, that’s what happens when you load all your images upfront. Instead, lazy-load images, so you’re only fetching what’s necessary, just like ordering one pizza at a time.

Using a library like react-lazyload is a quick fix:

import LazyLoad from 'react-lazyload';

<LazyLoad height={200} offset={100}>
  <img src="large-image.jpg" alt="Lazy Loaded Image" />
</LazyLoad>
Enter fullscreen mode Exit fullscreen mode

Why it helps: By lazy-loading images, you reduce the initial page load time and only download images when they’re needed—improving both performance and user experience.

3. useCallback and useMemo: Memory Boost for React

Just like how you keep reusing that same coffee mug to save time on washing, React can reuse values and functions if you let it! useCallback and useMemo are hooks that help you store expensive computations or functions, so they don’t get recalculated on every render.

useMemo Example:

const expensiveCalculation = (num) => {
  return num ** 2;
};

const MyComponent = ({ num }) => {
  const squaredNumber = React.useMemo(() => expensiveCalculation(num), [num]);

  return <div>{squaredNumber}</div>;
}
Enter fullscreen mode Exit fullscreen mode

useCallback Example:

const handleClick = useCallback(() => {
  console.log("Clicked");
}, []);
Enter fullscreen mode Exit fullscreen mode

Why it helps: With useMemo, React won’t have to redo expensive calculations unnecessarily. And useCallback stops you from creating a new function every render. This keeps React running smoothly—like upgrading its RAM!

4. Memoization with React.memo: Stop Unnecessary Re-renders

Do you have that one friend who repeats the same story over and over? React can be like that too—re-rendering components even when it doesn’t need to! This is where React.memo comes in, preventing React from re-rendering components unless their props change.

const MyComponent = React.memo(({ value }) => {
  return <div>{value}</div>;
});
Enter fullscreen mode Exit fullscreen mode

Why it helps: React.memo is like telling React, “Hey, you’ve heard this one before! Don’t repeat yourself unless there’s something new.” It avoids unnecessary re-renders, saving time and resources.

5. Efficiently Managing State: Lift It Only When Needed

Lifting state up is a common pattern in React, but sometimes we’re guilty of lifting it too high or managing too much state in the wrong places. This can cause excessive re-renders. Keep state local to components whenever possible, and avoid unnecessary re-renders by lifting state only when truly necessary.

const ParentComponent = () => {
  const [sharedState, setSharedState] = useState(false);

  return (
    <>
      <ChildComponent sharedState={sharedState} />
      <AnotherChild setSharedState={setSharedState} />
    </>
  );
}

const ChildComponent = ({ sharedState }) => {
  return <div>{sharedState ? 'Active' : 'Inactive'}</div>;
}

const AnotherChild = ({ setSharedState }) => {
  return <button onClick={() => setSharedState(true)}>Activate</button>;
}
Enter fullscreen mode Exit fullscreen mode

Why it helps: By managing state more carefully and lifting it only when needed, you can avoid unnecessary re-renders of sibling components. This keeps your app focused and efficient.

6. Debouncing User Input: Calm Down, React!

Imagine someone frantically typing into a search bar and your app trying to process every single keystroke. Poor React is probably sweating bullets! Enter debouncing—the process of only handling input after a user pauses, instead of on every single key press.

Using lodash.debounce can solve this problem:

import _ from 'lodash';

const Search = () => {
  const [query, setQuery] = useState('');

  const debouncedSearch = _.debounce((input) => {
    // Do your search logic
    console.log(input);
  }, 500);

  const handleChange = (e) => {
    setQuery(e?.target?.value);
    debouncedSearch(e?.target?.value);
  };

  return <input type="text" value={query} onChange={handleChange} />;
}
Enter fullscreen mode Exit fullscreen mode

Why it helps: Instead of React having a panic attack with every keystroke, debouncing gives it a breather. This ensures better performance when handling real-time user input, like search or form fields.

Conclusion: Optimizing React applications is not rocket science—it’s more like making sure you don’t drink six coffees in one sitting! From code-splitting to lazy-loading images, these techniques will help you keep your React app fast and responsive. So next time your app starts to feel sluggish, remember: it’s not React’s fault—it just needs a little optimization love!

Remember, optimizing a React app is a balance. You don’t need to throw all of these techniques in right away. Instead, identify your app’s bottlenecks, apply the appropriate optimizations, and watch your app become faster than you can finish your coffee!



Thanks for reading, If you liked the post please share it and leave suggestions.


Buy Me A Coffee

Connect With Me

Website: Hardik Gohil

Github: https://github.com/HardikGohilHLR

Linkedin: https://www.linkedin.com/in/hardikgohilhlr

Thanks ❤️

Top comments (0)