React App Performance Optimization Tips

Continuously improving the Web Application performance plays very important role to improve User Experience and keep users engaged.
While using React to develop Web Application, it is the developer responsibility to make sure putting optimization best techniques before publishing the final production bundle.
Lets see what all very important best optimization techniques we can apply to the React code.
Use Production Build
Another way of optimizing a React app is by making sure you bundle your app for production before deploying. By default, your app is in development mode, which means React will include helpful warnings. This can be very useful while you’re developing, but it can make your app size large and responses slower than usual. If your project is built with create-react-app
, you can fix this by running npm run build
before deploying, which will create a production-ready build of your app in a build/
folder that you can then deploy. You can confirm if your app is in either development or production mode using the React Developer Tools.
If you visit a site with React in production mode, the icon will have a dark background:

If you visit a site with React in development mode, the icon will have a red background:

Use React.Suspense and React.Lazy for Lazy Loading Components
Lazy loading is a great technique for optimizing and speeding up the render time of your app. The idea of lazy loading is to load a component only when it is needed. React comes bundled with the React.lazy
API so that you can render a dynamic import as a regular component. Here instead of loading your regular component like this:
import LazyComponent from './LazyComponent';
You can cut down the risk of performance by using the lazy method to render a component.
const LazyComponent = React.lazy(() => import('./LazyComponent'));
React.lazy
takes a function that must call a dynamic import()
. This will then return a Promise
which resolves to a module with a default
export containing a React component.
The lazy component should be rendered inside a Suspense
component, which allows you to add fallback content as a loading state while waiting for the lazy component to load.
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function MyComponent() {
return (
<div>
<p fallback={<section>Application is Loading....</p>}>
<LazyComponent />
</Suspense>
</div>
);
}
startTransition API
This is a new API introduced with this release, which helps in keeping the current webpage responsive and being able to do heavy non-blocking UI updates at the same time.
One important use case for startTransition
could be when a user starts typing in a search box. The input value has to be immediately updated while the search results could wait few milliseconds(as expected by the user).
This API provides a way to differentiate between quick updates and delayed updates. The delayed update(i.e. transition of one UI view to another) is termed as Transition Updates.
For urgent updates like typing, hover, clicking, we call props/functions usually like this :
setText(input)
For non-urgent or heavy UI updates, we can wrap it in a startTransition
API as :
startTransition(() => {
setText(input);
});
Automatic Batching
When groups of React multiple state updates into one render for improved performance is called batching.
For instance, React has always batched these into one re-render if you have two state updates inside the same click event. If you are running the following code, you’ll notice that while clicking every time, React only performs one code render, though you set the state the two times:

It is best for performance because it avoids unimportant re-renders. It also prevents the component from rendering half-finished states where a single state variable was updated only, creating bugs. You might think of a restaurant waiter who doesn’t run to his kitchen when you select the first dish but waits for you to complete your order.
Though, React wasn’t constant about when it batches updates. It is because React used to only batch updates during a browser event (like click), but here we’re updating the state after the event has already been handled (in fetch callback):

In the automatic batching (after updating your system to React 18), no matter where the states originate, it will always be re-rendered once.
Virtualize a Large List Using react-window
When you want to render an enormous table or list of data, it can significantly slow down your app’s performance. Virtualization can help in a scenario like this with the help of a library like react-window. react-window helps solve this problem by rendering only the items in the list that are currently visible, which allows for efficiently rendering lists of any size.
import React from 'react';
import { FixedSizeList as List } from 'react-window';
import './style.css';
const Row = ({ index, style }) => (
<div className={index % 2 ? 'ListItemOdd' : 'ListItemEven'} style={style}>
Row {index}
</div>
);
const Example = () => (
<List
className='List'
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</List>
);
React.memo for Component Memoization
React offers React.memo() HOC (high order component).
When React.memo() wraps a component, React memorizes the rendered output and then it skips the unwanted rendering.
Here’s how it works: When a function is rendered using this technique, it saves the result in memory, and the next time the function with the same arguments is called it returns the saved result without executing the function again, saving you bandwidth.
In the context of React, functions are the functional components, and arguments are props. Here’s an example:
import React from 'react';
const MyComponent = React.memo(props => {
/* render only if the props changed */
});
I hope this article will help you to further optimize your react application.
Stay tuned and subscribe my medium channel!!!