Friday, 30 April, 2021 UTC


Summary

Before shipping a React app, the least any team or developer needs to do is to check the performance and look to optimize the app for the end user’s experience.
Optimizing performance is an important technique to consider before shipping a React application. You can explore different ways of optimizing a React application that can enable a significant increase in speed and overall user experience for your applications.
Introduction
When building any React applications, a lot of thought goes into how the application should work and end up looking. The least any team or developer needs to do is to check the performance and look out for techniques to optimize the app for the end user’s experience. A lot of times you overlook this action, but in this article, I’ll be sharing five ways you can start optimizing your application for better performance.
React is a JavaScript library for building user interfaces. React ships with several ways to minimize the number of costly DOM operations required to update the UI. For many applications, using React will lead to a fast user interface without doing much work to specifically optimize for performance. Nevertheless, there are several ways you can speed up your React application. Let’s dive in and learn some of these techniques.
Use React.Fragment to Avoid Adding Extra Nodes to the DOM
When working with React, there are cases where you will need to render multiple elements or return a group of related items. Here’s an example:
function App() {
  return (
    <h1>Hello React!</h1>
    <h1>Hello React Again!</h1>
  );
}
If you try to run your app with the code above, you will run into an error stating that Adjacent JSX elements must be wrapped in an enclosing tag. This implies that you need to wrap both elements within a parent div.
function App() {
  return (
    <div>
      <h1>Hello React!</h1>
      <h1>Hello React Again!</h1>
    </div>
  );
}
Doing this will fix the error, but it comes with a degree of risk. You are adding an extra node to the DOM, which is not necessary. In a case like this, where the above is a child component that will be enclosed within a parent component, this becomes a problem.
function Table() {
  return (
    <table>
      <td>This is a Table Component</td>
      <Columns />
    </table>
  );
}
    
function Columns() {
  return (
    <div>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </div>
  );
}
The resulting HTML for the Table component will be invalid because of the additional div that was added.
function Table() {
  return (
    <table>
      <td>This is a Table Component</td>
      <div>
        <td>Hello React!</td>
        <td>Hello React Again!</td>
      </div>      
    </table>
  );
}
Let’s take a look at a better way of solving this by using React Fragment, which will not add any additional node to the DOM. The syntax looks like this:
function Columns() {
  return (
    <React.Fragment>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </React.Fragment>
  );
}
You can also use the short syntax <></> for declaring a Fragment.
function Columns() {
  return (
    <>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </>
  );
}
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 the React icon is blue with a dark background, it signifies your app is in production mode.
If your React app is in development mode, the icon switches to a red background as displayed in the image below.
Also it’s worth noting that if you are using React via a CDN you should remember to update React from development files to the ones suitable for production.
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
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>
    <Suspense fallback={<div>Loading....</div>}>
      <LazyComponent />
    </Suspense> 
  </div>
 );
}
Use React.memo for Component Memoization
React.memo is a great way of optimizing performance as it helps cache functional components.
In computing, memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
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 */
});
React.memo is a higher-order component and it’s similar to React.PureComponent but for using function components instead of classes.
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>
);
https://codesandbox.io/s/react-window-example-1mt85
Wrapping up
The techniques outlined above are all great ways for you to take into practice optimizing performance for your application. If there’s one thing you take away from this article, let it be that you should always make an effort to build a performant app that will significantly improve the speed of your application and your user’s experience by first building out the project and then optimizing performance where necessary; by doing this, you are just one step ahead in making your users happy. Thanks for reading and I hope you found this article helpful.
P.S. You can find me on Twitter @lauragift_ if you want to discuss more performance optimization techniques. :)