Search
Close this search box.
Search
Close this search box.
Search
Close this search box.

Best Practices for Optimizing the Performance of React Apps

Category:

Published:

March 9, 2022
monitor showing Java programming

React is a popular JavaScript library for building dynamic web applications with highly interactive user interfaces. It has all the features to reduce development time and boost your productivity. However, you need to know the best practices to get the most out of React. It will help you to optimize the performance of your apps significantly. Also, it will help you keep your code well organized. In this post, you will find five best practices for optimizing the performance of React apps.

Let’s dive in. 

What is React?

React is an open-source JavaScript library. It enables you to create rich and interactive user interfaces. It allows you to build large web applications that can modify data without reloading the page. Additionally, React helps you boost your productivity by utilizing reusable UI components which make the development process quicker and prevent code duplication. React is fast, scalable, and simple. As such, it has become very popular among developers around the globe. 

Why should you build applications with React?

  • It helps you to create dynamic web applications easily with less coding and more functionalities
  • It supports reusable components, which can reduce web application development time significantly
  • It’s easier to learn than other JavaScript front-end libraries, including Angular and Vue
  • It offers better code stability by following downward data flow to prevent parent structure from being affected by any modifications in its child structure
  • It supports dedicated tools, like React Developer Tool for Google Chrome, for debugging applications quickly and effectively

What are the best practices for optimizing the performance of React apps?

Use Lazy Loading for Speeding Up the Rendering Time

Lazy loading is a great technique for optimizing the performance of your React app. It focuses on loading a component only when it is needed. It enables you to speed up the render time of your app significantly. 

React features React.lazy API for allowing you to render a dynamic import as a regular component, so you don’t have to load your regular component like this:

import LazyComponent from './LazyComponent';

Instead, you can utilize lazy method to render the component, like this:

const LazyComponent = React.lazy(() => import('./LazyComponent'));

As you can see, React.lazy takes a function, which must call a dynamic import() function. Then it will return a Promise, which resolves to a module with a default export containing a React component.

Make sure to render the lazy component inside a Suspense component. It will allow you to add fallback content (f.e. a loading indicator/message) while waiting for the lazy component to load. Here is an example:

import React, { Suspense } from 'react';
    
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function MyComponent() {
  return (
  <div>
    <Suspense fallback={<div>Loading....</div>}>
      <LazyComponent />
    </Suspense> 
  </div>
 );
}

Avoid Additional HTML Element Wrappers by Using React.Fragments

There will be times when you will need to render multiple elements or return a group of related items in React, like this:

function App() {
    return (
        <div>
            <h1>Hello JavaScript</h1>
            <h1>Hello React</h1>
        </div>
    );
}

While using this code, you will get an error that states the following: “Adjacent JSX elements must be wrapped in an enclosing tag”. You can solve this issue by wrapping both the elements within the parent div. However, it will add an extra node to the DOM.

To avoid adding extra nodes to the DOM, you can use React.Fragments. Here is an example:

function Columns() {
    return (
        <React.Fragments>
            <td>Hello JavaScript</td>
            <td>Hello React</td>
        </React.Fragments>
    );
}

However, there is an even better syntax. Instead of using <React.Fragments>, you can simply use <> for declaring the fragment.

function Columns() {
    return (
        <>
            <td>Hello JavaScript</td>
            <td>Hello React</td>
        </>
    );
}

Save Bandwidth by Using React.memo

React.memo is a higher-order component. It helps you to optimize performance by caching functional components.

When a component is wrapped in React.memo(), React renders the component and memorizes the result. Before the next render, React reuses the memorized result while skipping the next rendering, provided that the given arguments or props are the same. In this way, React.memo can help you to save bandwidth.

Here is an example:

import React from 'react';

const MyComponent = React.memo(props =>  {
  /* render only if the props changed */
});

Render Large List without Affecting Performance by Using react-window

Rendering an enormous list of data can affect the performance of your app massively. You don’t want to see the users getting frustrated with sluggishness. In this case, you can try using react-window. It will render only the items in the list that are currently visible, like this:

Render Large List without Affecting Performance by Using react-window

Rendering an enormous list of data can affect the performance of your app massively. You don’t want to see the users getting frustrated with sluggishness. In this case, you can try using react-window. It will render only the items in the list that are currently visible, like this:

As you can see, the data is scrollable, so the users can view all the information conveniently. In addition, it will have a positive effect on the performance, as your app will not slow down.

Here is the code:

import React from "react";
import ReactDOM from "react-dom";
import { FixedSizeList as List } from "react-window";

import "./styles.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>
);

ReactDOM.render(<Example />, document.getElementById("root"));

Avoid Frequent Re-render by Using Reselect in Redux

Redux is a predictable state container for React. It helps you create JavaScript applications that behave consistently across client, server, and native environments. Reselect is a simple selector library for Redux. You can use it for building memorized selectors. It helps you to avoid frequent re-renders.

Let’s take a look at the code that doesn’t utilize Reselect:

const App = ({ comments, socialDetails }) => (
    <div>
      <CommentsContainer data={comments} />
      <ShareContainer socialDetails={socialDetails} />
    </div>
  );
  
  const addStaticPath = social => ({
    iconPath: `../../image/${social.iconPath}`
  });
  
  App = connect(state => {
    return {
        comments: state.comments,
        socialDetails: addStaticPath(state.social)
    };
  })(App);

Here, both CommentsContainer and ShareContainer will be re-rendered every time the comments data in state changes. It continues to happen even when addStaticPath doesn’t make any data changes to socialDetails. How can you fix the issue?

Let’s try rewriting addStaticPath with Reselect.

import { createSelector } from "reselect";
const socialPathSelector = state => state.social;
const addStaticPath = createSelector(
  socialPathSelector,
  social => ({
    iconPath: `../../image/${social.iconPath}`
  })
);

Now, the issue will be fixed, as reselect will return only the last function result until the new inputs are being passed.

Wrapping Up

That’s it! Now, you have learned different ways of optimizing the performance of React applications. By following these steps, you can enhance the speed of your apps significantly and deliver the best experience to the users.


Interested in joining our Technology team at Dialectica? Visit our dedicate Technology Careers page to explore our Software Engineer, Cloud Engineer and more tech job vacancies. Apply today for our Senior Data Engineer, Business Intelligence (BI), Full Stack, Front-end Developer, Back-end Developer jobs in Athens and become a member of #teamDialectica.

Share