Optimization Techniques for Lightning-Fast React Apps

In the field of application development, the demand for optimized and high-performance applications is rapidly increasing. Because nowadays we have to handle large amounts of data with better user experience and very minimal loading time.

Assume that you are having an Ecommerce website which is not efficient and laggy. How will your customers approach this site? The customers will get frustrated right? They would likely become frustrated. This is where optimization comes in.

Optimization is a technique that improves overall performance, speed, and user experience by implementing corrective measures.

How can we say that an app is optimized?

Simply, an efficient, high-performing, and super-fast application can be called an optimized Application. 

If you're looking to optimize your applications, there are a few things you can do. First, make sure that your code is well written and efficient. This means that you should avoid using unnecessary loops or functions and instead focus on making your code as streamlined as possible.

Here we are discussing some of the essential optimization techniques that are available in React JS.

They are memoization, virtualization, IndexedDB, streaming data, lazy loading, React Suspense, and concurrent rendering.

Memoization

Memoization is a technique that involves caching the results of a function so that it does not have to recalculate them every time the function is called. This technique is used to optimize complex calculations that doesn't change often, for example rendering heavy UI graphs.

import React, { useMemo } from "react";

const ReactMemoization = ({ somedata }) => {

const memoizedResult = useMemo(() => complexCalculation(data), [data]);

return <div>{memoizedReult}</div>;

};
 
const complexCalculation = (data) => {
 
//  some complex calculations performs here

return data;
 
};
 

Virtualization

Virtualization is a technique that involves rendering only the components that are visible on the screen and not the entire component hierarchy. This technique reduces the number of components that need to be rendered and enhances the app’s response to user interactions.

import React from "react";

import { List } from "react-virtualized";

const  ReactVirtualization = ({ data }) => {

return (
 
<List

width={500}

height={500}

rowCount={data.length}

rowHeight={20}

rowRenderer={({ index, style }) => (

<div style={style}>{data[index]}</div>

)}

/>
 
);
 
};


Lazy Loading

Lazy loading is a technique that is used for loading only the components that are needed at a given time and not the entire component hierarchy upfront. For large apps with many components, it reduces the amount of data that needs to be loaded and enhances the app’s response to user interactions.

import React, { lazy, Suspense } from "react";

const ReactLazyComponent = lazy(() => import("./LazyComponent"));

const LazyLoading = () => {

return (
   
<Suspense fallback={<p>Loading...</p>}>
     
<ReactLazyComponent />
   
</Suspense>
 
);

};

export default LazyLoading ;


React Suspense

React Suspense allows you to declaratively specify how your app should behave while data is being loaded. A simple example would be to show a loading indicator while the data is being fetched:

const resource = fetchData();

const ReactSuspense = ()=> {
 
return (
   
<Suspense fallback={<div>Loading...</div>}>
     
<DataComponent resource={resource} />
 
</Suspense>
 
);

}

const DataComponent =({ resource })=> {
 
const data = resource.read();

 return <div>{data}</div>;

}


Concurrent Rendering

Concurrent rendering is a technique that allows multiple rendering tasks to be performed simultaneously, rather than waiting for one task to complete before starting another. This optimization enhances the app’s responsiveness to user interactions and delivers a smooth, seamless experience. Here’s an example of how to use the React.unstable_ConcurrentMode:

//  This comes built-in with the React 18 version update.

ReactDOM.render(

<React.unstable_ConcurrentMode>

<App />

</React.unstable_ConcurrentMode>,

 document.getElementById("root")
 
);

 

Streaming Data

In this approach data is loaded incrementally instead of loading the entire data at once, reducing the amount of data that needs to be loaded and improving the app’s response to user interactions.

import React, { useState, useEffect } from 'react';

interface Game{

name: string;

playersCount: number;

}

const App: React.FC = () => {

const [games, setGames] = useState<Game[]>([]);

useEffect(() => {
   
const eventSource = neEventSource('http://localhost:4000/datastream');
   
eventSource.onmessage = (event) => {

const game: Game = JSON.parse(event.data);

setGames((prevGames) => [...prevGames, games]);

};
   
return () => {
     
eventSource.close();
   
};
 
}, []);

 return (
   
<ul>
     
{games.map((game) => (
       
<li key={game.name}>{game.name} ({game.playersCount})</li>
     
))}
   
</ul>
 
);

};

export default App;


IndexedDB

IndexedDB is browser-based storage that helps you to keep large amounts of data locally on the user’s browser. With this technique, we can store data locally and retrieve it even faster. This can avoid frequent interaction with the server and can significantly improve the app's performance and speed.

Conclusion

Therefore by implementing these optimization techniques we can substantially boost the React application performance, speed and user experience. As it is in high demand in the modern era, we can expect much more techniques in the upcoming days.

Sibin John