DEV Community

Joodi
Joodi

Posted on

πŸ₯ˆ React Performance Tips: 12 Ways to Make Your App Faster

React is fast by default.

But as an application grows, unnecessary renders, large lists, too much JavaScript, and excessive API requests can make it slower.

The good news is that you don't need complicated tricks everywhere.

Let's look at 12 practical ways to improve React performance, from simple improvements to more advanced techniques.

1. Stop Rendering What You Don't Need

Every time a component renders, React runs its component function again.

That doesn't mean every render is a problem. The problem is doing expensive work when nothing actually changed.

For example, avoid putting unrelated state in a component that contains a large part of your UI.

Instead, keep components focused so an update only affects the part of the UI that actually needs it.

The goal isn't to prevent every render.

The goal is to avoid unnecessary work.

2. Keep Your State in the Right Place

Don't move every piece of state to the top of your application.

If only one component needs the state, keep it there.

function SearchBox() {
  const [query, setQuery] = useState("");

  return (
    <input
      value={query}
      onChange={(e) => setQuery(e.target.value)}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Keeping state close to where it is used can reduce unnecessary updates in other parts of the application.

Keep state as close as possible to the components that use it.

3. Don't Store Data You Can Calculate

Not everything needs useState.

For example, don't store fullName separately if you already have firstName and lastName.

Avoid:

const [fullName, setFullName] = useState("");

useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);
Enter fullscreen mode Exit fullscreen mode

Just calculate it:

const fullName = `${firstName} ${lastName}`;
Enter fullscreen mode Exit fullscreen mode

This avoids unnecessary state and an unnecessary Effect.

A simple rule:

If you can calculate it during render, you probably don't need state for it.

4. Make Large Lists Faster

Rendering thousands of elements can become expensive.

Imagine a chat application with 10,000 messages.

You don't need all 10,000 messages in the DOM at the same time.

For large lists, consider:

  • Virtualization
  • Pagination
  • Infinite scrolling

Virtualization keeps only the visible items, plus a small buffer, mounted in the DOM.

Libraries such as react-window can help with this.

Don't add virtualization to every list. A list with 50 items probably doesn't need it.

5. Load Heavy Components Only When Needed

Your users shouldn't have to download code they don't need immediately.

React supports lazy loading with lazy and Suspense:

const Settings = lazy(() => import("./Settings"));
Enter fullscreen mode Exit fullscreen mode

Now the Settings component can be loaded when it is needed instead of being included in the initial JavaScript.

This is useful for heavy or rarely visited features such as:

  • Charts
  • Editors
  • Maps
  • Settings pages
  • Large dashboards

Smaller initial bundles usually mean faster initial loading.

6. Keep Search and UI Interactions Responsive

Some updates don't need to happen immediately.

For example, a search input should respond instantly while filtering thousands of results can happen at a lower priority.

React provides useTransition and useDeferredValue for these situations.

You can also debounce user input:

const debouncedSearch = useDebounce(search, 500);
Enter fullscreen mode Exit fullscreen mode

Instead of sending a request on every keystroke, you can wait until the user stops typing.

These techniques are useful for search, filtering, large lists, and complex dashboards.

7. Avoid Unnecessary API Requests

Performance isn't only about rendering.

Too many network requests can also make your application feel slow.

Depending on your application, consider:

  • Caching responses
  • Request deduplication
  • Pagination
  • Debouncing search
  • Canceling outdated requests

For example, if a user quickly searches for:

react
react performance
react performance optimization
Enter fullscreen mode Exit fullscreen mode

you don't necessarily want three requests running at the same time.

The goal is simple:

Don't make the network do work you don't need.

8. Memoization: When Should You Actually Use It?

React provides three common memoization tools:

  • useMemo caches a calculation result.
  • useCallback caches a function reference.
  • React.memo can skip a component render when its props haven't changed.

For example:

const filteredUsers = useMemo(() => {
  return users.filter(user =>
    user.name.includes(search)
  );
}, [users, search]);
Enter fullscreen mode Exit fullscreen mode

But don't add memoization everywhere.

Memoization also has a cost and adds complexity.

Use it when:

  • A calculation is expensive.
  • A component renders unnecessarily.
  • A stable reference is actually useful.

Don't optimize code that doesn't have a performance problem.

9. React Compiler: Less Manual Optimization

Modern React introduces another important piece: React Compiler.

The Compiler can automatically optimize components, values, and functions in many cases, reducing the need for manual memoization.

That means you shouldn't automatically think:

useMemo(...)
useCallback(...)
React.memo(...)
Enter fullscreen mode Exit fullscreen mode

whenever you see a performance problem.

First ask:

Is there actually a performance problem?

If React Compiler is enabled for your project, let it handle the optimizations it can, and use manual memoization when you have a specific reason to do so.

10. Use Stable Keys and References

Keys help React identify items in a list.

Prefer:

items.map(item => (
  <Item key={item.id} />
));
Enter fullscreen mode Exit fullscreen mode

Instead of:

items.map((item, index) => (
  <Item key={index} />
));
Enter fullscreen mode Exit fullscreen mode

Stable keys help React understand which item was added, removed, or changed.

The same idea applies to object and function references.

Creating new objects or functions on every render can matter when you're working with memoized components.

11. Find the Real Bottleneck

Once you understand the common optimization techniques, don't guess.

Use React DevTools Profiler to see which components render and how much time they take.

You can also use the browser's Performance panel to investigate:

  • Long tasks
  • Slow scripting
  • Layout work
  • Rendering problems

Instead of saying:

"This component feels slow."

Find out why it is slow.

12. Measure Again Before You Ship

After making an optimization, measure the result again.

Did the render time improve?

Did the bundle become smaller?

Did the interaction become more responsive?

If the change doesn't improve anything, you may not need it.

Performance Checklist

Before shipping your React application, ask:

  • Am I rendering unnecessary UI?
  • Is my state in the right place?
  • Am I storing values I can calculate?
  • Are large lists handled efficiently?
  • Am I loading heavy code only when needed?
  • Are search and interactions responsive?
  • Am I making unnecessary API requests?
  • Am I using memoization for a real reason?
  • Can React Compiler handle the optimization?
  • Am I using stable keys?
  • Did I measure the actual bottleneck?
  • Did I verify the improvement afterward?

The best React optimization isn't adding more code.

It's making React do less unnecessary work.

Top comments (0)