Blog

339

Top 8 React Optimization Techniques You Should Know

Software developers working on web applications need to have React optimization techniques at the forefront of their minds. Optimizing application performance is vital for developers who want to make sure users have a good experience and stay on an app.

Research shows that even a delay of a second in load time causes approximately a 7% drop in conversions. This simply signifies that developers MUST be abreast with react performance tips at all times. Their knowledge of React performance optimization will help them build user-friendly apps.

By default, React apps have a very fast user interface. But as an app gets bigger, developers may run into performance problems.

In this guide, we’ll talk about the top 8 react optimization techniques to improve the performance of a React app.

Are you ready to explore?

Let’s dive in…

1. Using React.PureComponent

The first and foremost react optimization technique includes using React.PureComponent. If you are familiar with React, you are also familiar with React.Component. It is most likely what you extend whenever you create a new domain-specific component.

React.PureComponent is primarily used to optimize react.js performance. In certain situations, you can use React.PureComponent to improve performance if your React component render() function produces the same output given the same props and state.

React’s function components and PureComponent offer two distinct approaches to react performance optimization at the component level.

Function components prevent the construction of class instances while reducing the overall size of the bundle because they minify more efficiently than classes.

Alternatively, to optimize UI update performance, we can try converting function components to the PureComponent class.

Nevertheless, if the Component does not employ state and other life cycle methods, the initial render time is more complex than function components with potentially faster updates.

React.PureComponent compares state changes superficially. This means that it compares values for primitive data types and references for objects. As a result, we must ensure that two conditions are met when utilizing React.PureComponent:

  • The Component State/Props object is immutable;
  • State/Props should not have nested objects with many levels.

2. Use React.memo for Component Memorization

Another vital react optimization technique includes the use of React.memo. React.memo is a component of a higher order. It is comparable to a PureComponent, but the difference is that a PureComponent is part of the class implementation for Component, whereas the “memo” variable is employed in the production of functional component instances.

In React.memo, the rendering of the Component will be omitted if the input props are identical, which results in the Component being both quicker and more efficient.

The efficiency of the application is improved as a result of its memorization of the output of the most recent execution of a particular input prop. Also, you have the option of passing in your own individualized comparison logic for this Component.

A user would be able to search for a more in-depth comparison of the object using the user’s own unique logic. In the event that the comparison function returns a value that is not true, the Component in question will be re-rendered; otherwise, the Component in question will not be re-rendered.

function CustomisedComponen(props) {

    return (

        <div>

            <b>User name: {props.name}</b>

            <b>User age: {props.age}</b>

            <b>User designation: {props.designation}</b>

        </div>

    )

}

// The Component below is the optimized version for the Default Component

// The Component will not re-render if same props value for “name” property

var memoComponent = React.memo(CustomisedComponent);

The preceding Component will perform a quick comparison between the previous and subsequent props’ values. In situations when object references are supplied as props to the memo component, a specific login is required for the comparison.

In such situations, the comparison function can be used as the input string to the React.memo function.

Assume that the props value (user) is an item reference containing the person’s name, age, and designation.

In this instance, a thorough comparison is required. We may write a custom function that compares the previous and next props values for name, age, and designation and yields false if they are not identical.

Thus, our component will not be re-rendered, even if the memo component receives reference data as input. Here is a custom logic for comparison:

// The following function takes “user” Object as input parameter in props

function CustomisedComponen(props) {

    return (

        <div>

            <b>User name: {props.user.name}</b>

            <b>User age: {props.user.age}</b>

            <b>User designation: {props.user.designation}</b>

        </div>

    )

}

function userComparator(previous Props, nextProps) {

    if(previosProps.user.name == nextProps.user.name ||

       previosProps.user.age == nextProps.user.age ||

       previosProps.user.designation == nextProps.user.designation) {

        return false

    } else {

        return true;

    }

}

var memoComponent = React.memo(CustomisedComponent, userComparator);

3. React useMemo Hook

useMemo() Hook is one of the best react optimization techniques. useMemo is a React hook that is used to cache functions in React, particularly ones that need a lot of CPU time.

The useMemo Hook can be used to prevent costly, resource-intensive processes from executing unnecessarily.

Let’s see an example:

import { useState } from “react”;

import ReactDOM from “react-dom/client”;

const App = () => {

const [count, setCount] = useState(0);

const [todos, setTodos] = useState([]);

const calculation = expensiveCalculation(count);

const increment = () => {

    setCount((c) => c + 1);

};

const addTodo = () => {

    setTodos((t) => […t, “New Todo”]);

};

return (

    <div>

      <div>

        <h2>My Todos</h2>

        {todos.map((todo, index) => {

          return <p key={index}>{todo}</p>;

        })}

        <button onClick={addTodo}>Add Todo</button>

      </div>

      <hr />

      <div>

        Count: {count}

        <button onClick={increment}>+</button>

        <h2>Expensive Calculation</h2>

        {calculation}

      </div>

    </div>

);

};

const expensiveCalculation = (num) => {

console.log(“Calculating…”);

for (let i = 0; i < 1000000000; i++) {

    num += 1;

}

return num;

};

const root = ReactDOM.createRoot(document.getElementById(‘root’));

root.render(<App />);

In this example, an expensive function is executed on every render. When modifying the count or adding tasks, execution will be delayed.

Using useMemo, we can resolve this performance issue. All we need to do is to memorize the expensiveCalculation method using the useMemo Hook. This will only execute the function when necessary.

The useMemoHook supports a second parameter for dependency declaration. The expensive function will only execute if its dependencies change. Here is an example:

import { useState, useMemo } from “react”;

import ReactDOM from “react-dom/client”;

const App = () => {

const [count, setCount] = useState(0);

const [todos, setTodos] = useState([]);

const calculation = useMemo(() => expensiveCalculation(count), [count]);

const increment = () => {

    setCount((c) => c + 1);

};

const addTodo = () => {

    setTodos((t) => […t, “New Todo”]);

};

return (

    <div>

      <div>

        <h2>My Todos</h2>

        {todos.map((todo, index) => {

          return <p key={index}>{todo}</p>;

        })}

        <button onClick={addTodo}>Add Todo</button>

      </div>

      <hr />

      <div>

        Count: {count}

        <button onClick={increment}>+</button>

        <h2>Expensive Calculation</h2>

{calculation}

      </div>

    </div>

);

};

const expensiveCalculation = (num) => {

console.log(“Calculating…”);

for (let i = 0; i < 1000000000; i++) {

    num += 1;

}

return num;

};

const root = ReactDOM.createRoot(document.getElementById(‘root’));

root.render(<App />);

In the example above, the expensive function will only execute when the count variable is modified and not when new to-do items are added.

TOOK FROM: https://www.w3schools.com/react/react_usememo.asp

4. Lazy Loading

Lazy loading, also known as code splitting and data fetching, is not novel. It has been accessible for quite a while. It simply means that a component or portion of code must be loaded only when needed.

React bundles and deploys the entire codebase simultaneously. Typically, this is a good approach, given that React SPAs (single page applications) are fairly small and have a little performance impact.

However, it does not seem prudent to load the entire program in the case of a massive program, such as a content management system with a client portal, an admin site, etc.

A massive application will require a great deal of redundant data transfer, resulting in a website that loads slowly. Also, a client login does not have access to admin-only features; hence it is a waste of memory and time to load them.

Lazy() in React enables you to load React components asynchronously via code splitting without any extra libraries.

In circumstances where it is known that not all users will have access to particular code or features, or when the user does not access them regularly, it is ideal only to load them when the user requests them. This enhances both the user experience and initial loading time.

5. Virtualize Long Lists

“Windowing” is yet another one of the best react optimization techniques that developers can use for react performance optimization.

If your application is responsible for the rendering of lengthy data lists (hundreds or thousands of rows), “windowing” is your best bet! It renders only a tiny portion of your rows at any given time.

Using this method, you can significantly cut down on the amount of time required to re-render the components and the number of DOM nodes that are generated.

Windowing libraries such as react-window and react-virtualized are quite popular. They offer a number of reusable components that may display tabular data, list data, and grid data, respectively. However, you can also design your own windowing component, just like Twitter did.

6. Using Reselect Selectors

The use of reselect improves the efficiency of our Redux state management. Since Redux adheres to the principle of immutability, new object references will be created each time action dispatch occurs. Because of this, performance will be negatively impacted because re-rendering will be triggered on components even when the object references change, but the fields have remained the same.

The Reselect library encodes the Redux state, examines the fields of the state, and communicates to React whether or not the fields should be rendered based on whether or not they have changed.

Therefore, using reselect helps save valuable time because it does a shallow traversal between the prev and current Redux state fields to determine whether or not they have changed, even though they use distinct memory references.

If any of the fields have been modified, it notifies React to do a new render; however, if none of the fields have been modified, it aborts the new render despite creating a new state object.

7. Code Splitting

Code splitting is another indispensable react optimization technique. Developers often use this technique to optimize react js performance.

When a React app runs in a browser, by default, a “bundle” file that contains the whole app’s code loads and serves it all at once to users. This file contains all the code files that a web application needs to work.

Bundling is a good idea because it cuts down on how many HTTP requests a page can handle. However, when an app’s files grow in size, the bundle file also grows in size. This, in turn, slows down the first-page load, which disappoints the user.

With code-splitting, React lets developers break up a large bundle file into multiple chunks using dynamic import() and then load these chunks on-demand using React.lazy. This strategy makes a complex React application’s page load much faster.

For code-splitting to work, we change a normal React import into this:

import Home from “./components/Home”;

import About from “./components/About”;

After that, the following:

const Home = React.lazy(() => import(“./components/Home”));

const About = React.lazy(() => import(“./components/About”));

This code instructs React to conditionally load each component. Therefore, when a user clicks on a link to the homepage, for example, React merely downloads the file for the requested page as opposed to loading a big bundle file for the entire application.

Following the import, we must render the lazily loaded components within a Suspense component as follows:

<React.Suspense fallback={<p>Loading page…</p>}>

 <Route path=”/” exact>

    <Home />

</Route>

 <Route path=”/about”>

    <About />

 </Route>

</React.Suspense>

The Suspense component enables us to showcase a loading text as an alternative, while React renders the lazy Component in the UI.

8. Use shouldComponentUpdate

Using shouldComponentUpdate is another crucial react optimization technique to stop renders that aren’t necessary.

Most problems with react js performance can be fixed by making small changes. These changes, however, can make your app better and faster. And the shouldComponentUpdate is one such method.

Implementing shouldComponentUpdate can make your React app run faster in a way that can be measured and seen.

shouldComponentUpdate is a hook in the React lifecycle that lets you tell React not to re-render a certain component if its state hasn’t changed.

For example, you have a list with a lot of parts and a complicated structure, and one of those parts changes. Understand that unneeded list items consume app resources. By implementing shouldComponentUpdate, you can command React to ignore everything but the changed Component.

Wrapping it up…

So, these are the top 8 react optimization techniques you can use to significantly boost react js performance. The majority of these methods or suggestions do not call for the use of complex software.

Remember that before you use these react optimization techniques, you must first identify a performance issue within your application that needs to be addressed. Using these react performance tips you can optimize your application performance for a more positive experience for the end-user.

Do let us know which of the above outlined react performance tips piqued your curiosity!