ReactJS - Optimizing Performance



React internally handles the performance of the application and optimize it on every opportunities. As a developer, we can do certain things to get maximum performance of our application. Let us see some of the techniques to get maximum performance out of react library in this chapter.

Techniques of Performance Optimization

Some of the techniques of performance optimization are as follows −

Use production build − React has two mode, development and production. Development mode is for the developers, Development mode enables lot of useful stuff for developer to get better inside of the application and to debug the application. This will slow down the application. To get maximum performance, enable the production mode and deploy the application.

CDN Application using cdn to link the react library should use production build of the react library as shown below −

<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

Create react app − Application created using create-react-app CLI can use below command to create production version of the application.

npm run build

Brunch − Application using brunch should install terser-brunch plugin and then invoke production build to get efficient and performance code.

npm install --save-dev terser-brunch
brunch build -p

Rollup − Application using rollup should install commonjs, replace and terser plugins and configure it to get best production version.

npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser

Use React devtools − React provides development tools for all browsers as extension. Once the extension is installed, the developer tools section of the browser will show a dedicated section for react. One of the tool provided by react extension is Profiler (React DevTool Profiler). The application can be profiled and optimized before deploying the application to the production.

Windowing technique − If the data to be shown in the front end is huge, then the performance of the application will get affected instantly. One way is to show only a small subset of the data through pagination and other similar technique. If those techniques are not feasible, React recommends windowing technique, which will render only a small subset of data at a time automatically. We will learn by applying window technique later in this chapter.

Avoid Reconciliation (shouldComponentUpdate) − Reconciliation is a a powerful technique to increase the performance of the react application. Still, reconciliation takes some time to run and apply it in our application. Skipping rendering (and subsequently reconciliation) will improve the performance. React provides an API, shouldComponentUpdate to give hint to the react core whether to skip or continue the rendering. Below code will skip the rendering of the application

shouldComponentUpdate(nextProps, nextState) {
   return false;
}

Components can analyze its current state and props with its updated one and decide whether the rendering part can be skipped.

Pure component − Instead of writing shouldComponentUpdate, write a pure version of component by extending React.PureComponent. Pure component will usually emit same output if the given input is same. Pure component will do the shallow comparison and skip the reconciliation. But, there is one issue. If the changes are no shallow, then react skip the updates and rendering. To fix it, it is enough that the changes are done through visible mutation as shown below −

// non-mutation (wrong way to code)
const words = this.state.words;
words.push('john');
this.setState({words: words});

// mutated version (right way to code)
this.setState(state => ({
   words: state.words.concat(['marklar'])
}));

Here,

  • In the first version of the code, the object is not mutated. So the comparison with old object succeeds and skip the reconciliation.

  • In the second version of the code, the object is mutated and will get caught during comparison.

Applying windowing technique

Let us create a new react application to render a large user list by applying windowing technique in this section.

First of all, create a new react application and start it using below command.

create-react-app myapp
cd myapp
npm start

Next, install the bootstrap and react-bootstrap library using below command,

npm install --save react-window

Next, open App.css (src/App.css) and remove all CSS classes.

// remove all css classes

Next, create a file, users.json under public folder and populate with below user information,

[
   {
      "id":1,
      "name":"Fowler",
      "age":18
   },
   {
      "id":2,
      "name":"Donnell",
      "age":24
   },
   {
      "id":3,
      "name":"Pall",
      "age":26
   },
   {
      "id":4,
      "name":"Christos",
      "age":19
   },
   {
      "id":5,
      "name":"Dud",
      "age":29
   },
   {
      "id":6,
      "name":"Rayner",
      "age":22
   },
   {
      "id":7,
      "name":"Somerset",
      "age":31
   },
   {
      "id":8,
      "name":"Stavros",
      "age":32
   },
   {
      "id":9,
      "name":"Cody",
      "age":19
   },
   {
      "id":10,
      "name":"Sharai",
      "age":19
   },
   {
      "id":11,
      "name":"Kristo",
      "age":28
   },
   {
      "id":12,
      "name":"Harvey",
      "age":27
   },
   {
      "id":13,
      "name":"Christen",
      "age":27
   },
   {
      "id":14,
      "name":"Hillard",
      "age":19
   },
   {
      "id":15,
      "name":"Jaine",
      "age":32
   },
   {
      "id":16,
      "name":"Annabel",
      "age":29
   },
   {
      "id":17,
      "name":"Hildagarde",
      "age":29
   },
   {
      "id":18,
      "name":"Cherlyn",
      "age":18
   },
   {
      "id":19,
      "name":"Herold",
      "age":32
   },
   {
      "id":20,
      "name":"Gabriella",
      "age":32
   },
   {
      "id":21,
      "name":"Jessalyn",
      "age":32
   },
   {
      "id":22,
      "name":"Opal",
      "age":31
   },
   {
      "id":23,
      "name":"Westbrooke",
      "age":27
   },
   {
      "id":24,
      "name":"Morey",
      "age":22
   },
   {
      "id":25,
      "name":"Carleton",
      "age":26
   },
   {
      "id":26,
      "name":"Cosimo",
      "age":22
   },
   {
      "id":27,
      "name":"Petronia",
      "age":23
   },
   {
      "id":28,
      "name":"Justino",
      "age":32
   },
   {
      "id":29,
      "name":"Verla",
      "age":20
   },
   {
      "id":30,
      "name":"Lanita",
      "age":18
   },
   {
      "id":31,
      "name":"Karlik",
      "age":23
   },
   {
      "id":32,
      "name":"Emmett",
      "age":22
   },
   {
      "id":33,
      "name":"Abran",
      "age":26
   },
   {
      "id":34,
      "name":"Holly",
      "age":23
   },
   {
      "id":35,
      "name":"Beverie",
      "age":23
   },
   {
      "id":36,
      "name":"Ingelbert",
      "age":27
   },
   {
      "id":37,
      "name":"Kailey",
      "age":30
   },
   {
      "id":38,
      "name":"Ralina",
      "age":26
   },
   {
      "id":39,
      "name":"Stella",
      "age":29
   },
   {
      "id":40,
      "name":"Ronnica",
      "age":20
   },
   {
      "id":41,
      "name":"Brucie",
      "age":20
   },
   {
      "id":42,
      "name":"Ryan",
      "age":22
   },
   {
      "id":43,
      "name":"Fredek",
      "age":20
   },
   {
      "id":44,
      "name":"Corliss",
      "age":28
   },
   {
      "id":45,
      "name":"Kary",
      "age":32
   },
   {
      "id":46,
      "name":"Kaylee",
      "age":21
   },
   {
      "id":47,
      "name":"Haskell",
      "age":25
   },
   {
      "id":48,
      "name":"Jere",
      "age":29
   },
   {
      "id":49,
      "name":"Kathryne",
      "age":31
   },
   {
      "id":50,
      "name":"Linnea",
      "age":21
   },
   {
      "id":51,
      "name":"Theresina",
      "age":24
   },
   {
      "id":52,
      "name":"Arabela",
      "age":32
   },
   {
      "id":53,
      "name":"Howie",
      "age":22
   },
   {
      "id":54,
      "name":"Merci",
      "age":21
   },
   {
      "id":55,
      "name":"Mitchel",
      "age":30
   },
   {
      "id":56,
      "name":"Clari",
      "age":18
   },
   {
      "id":57,
      "name":"Laurena",
      "age":19
   },
   {
      "id":58,
      "name":"Odessa",
      "age":30
   },
   {
      "id":59,
      "name":"Pippy",
      "age":25
   },
   {
      "id":60,
      "name":"Wilmar",
      "age":23
   },
   {
      "id":61,
      "name":"Cherianne",
      "age":24
   },
   {
      "id":62,
      "name":"Huberto",
      "age":25
   },
   {
      "id":63,
      "name":"Ariella",
      "age":26
   },
   {
      "id":64,
      "name":"Lorant",
      "age":30
   },
   {
      "id":65,
      "name":"Francesca",
      "age":25
   },
   {
      "id":66,
      "name":"Ingamar",
      "age":28
   },
   {
      "id":67,
      "name":"Myrta",
      "age":27
   },
   {
      "id":68,
      "name":"Nicolette",
      "age":26
   },
   {
      "id":69,
      "name":"Petra",
      "age":22
   },
   {
      "id":70,
      "name":"Cyrill",
      "age":27
   },
   {
      "id":71,
      "name":"Ad",
      "age":23
   },
   {
      "id":72,
      "name":"Denys",
      "age":22
   },
   {
      "id":73,
      "name":"Karilynn",
      "age":23
   },
   {
      "id":74,
      "name":"Gunner",
      "age":30
   },
   {
      "id":75,
      "name":"Falkner",
      "age":20
   },
   {
      "id":76,
      "name":"Thurston",
      "age":19
   },
   {
      "id":77,
      "name":"Codi",
      "age":30
   },
   {
      "id":78,
      "name":"Jacob",
      "age":31
   },
   {
      "id":79,
      "name":"Gasparo",
      "age":26
   },
   {
      "id":80,
      "name":"Mitzi",
      "age":29
   },
   {
      "id":81,
      "name":"Rubetta",
      "age":21
   },
   {
      "id":82,
      "name":"Clary",
      "age":20
   },
   {
      "id":83,
      "name":"Oliviero",
      "age":24
   },
   {
      "id":84,
      "name":"Ranique",
      "age":21
   },
   {
      "id":85,
      "name":"Shae",
      "age":24
   },
   {
      "id":86,
      "name":"Woodrow",
      "age":20
   },
   {
      "id":87,
      "name":"Junia",
      "age":31
   },
   {
      "id":88,
      "name":"Athene",
      "age":26
   },
   {
      "id":89,
      "name":"Veriee",
      "age":18
   },
   {
      "id":90,
      "name":"Rickie",
      "age":30
   },
   {
      "id":91,
      "name":"Carly",
      "age":23
   },
   {
      "id":92,
      "name":"Vern",
      "age":19
   },
   {
      "id":93,
      "name":"Trix",
      "age":26
   },
   {
      "id":94,
      "name":"Lenore",
      "age":20
   },
   {
      "id":95,
      "name":"Hanna",
      "age":30
   },
   {
      "id":96,
      "name":"Dominique",
      "age":21
   },
   {
      "id":97,
      "name":"Karlotta",
      "age":22
   },
   {
      "id":98,
      "name":"Levey",
      "age":20
   },
   {
      "id":99,
      "name":"Dalila",
      "age":18
   },
   {
      "id":100,
      "name":"Launce",
      "age":21
   }
]

Next, create a simple user list component, SimpleWindow (src/Components/SimpleWindow.js) and render a user list by applying windows feature as shown below −

import React from "react";
import { FixedSizeList as List } from 'react-window';
class SimpleWindow extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: []
      };
   }
   componentDidMount() {
      fetch("users.json")
         .then((response) => response.json())
         .then((data) => {
            this.setState({
               data: data
            });
         });
   }
   render() {
      return (
         <List
            innerElementType="ul"
            itemData={this.state.data}
            itemCount={this.state.data.length}
            itemSize={35}
            width={500}
            height={300}
         >
         {
            ({data, index, style}) => {
               return (
                  <li style={style}>
                     {data[index].name}
                  </li>
               )
            }
         }
         </List>
      )
   }
}
export default SimpleWindow

Here we have,

  • Imported FixedSizeList component as List.

  • Fetched user list from users.json url using fetch method in componentDidMount() lifecycle event.

  • Rendered the use list using FixedSizeList component.

  • innerElementType props of FixedSizeList component refers the element to be generated inside the component.

  • itemData, itemCount and itemSize refers the item list, total number of available items and size of the each item.

Next, open App component (src/App.js), and include SimpleWindow component as shown below −

import './App.css'
import React from 'react';
import SimpleWindow from './Components/SimpleWindow'
function App() {
   return (
      <div className="container">
         <div style={{ padding: "10px" }}>
            <div>
               <SimpleWindow />
            </div>
         </div>
      </div>
   );
}
export default App;

Here,

  • Imported our new component SimpleWindow using import statement

  • Rendered our new SimpleWindow component.

Finally, open the application in the browser and check the final result. Table component will be rendered as shown below −

Applying Windowing Technique

Summary

React optimizes the application out of the bax. Also, React library improves optimization in each and every release. In addition to those optimization, We can follow the above discussed technique to improve performance from our end.

Advertisements