React Tutorial: Top 7 optimization techniques in React App

React Tutorial: Top 7 optimization techniques in React App

In this article, you'll learn various optimization methods that use these inbuilt APIs, lifecycle methods and some other general techniques that ensure you improve your React code

In this article, you'll learn various optimization methods that use these inbuilt APIs, lifecycle methods and some other general techniques that ensure you improve your React code

One key factor for positive user experience is speed i.e how much time a user has to wait to first see contents from your website or application. Amazon reports a 1% sales loss for every 100ms load time, Walmart reports a +2% conversion per one second load time improvement.

Negative statistics lead to a decrease in user satisfaction and eventually customers. One solution to mitigating this is to properly optimize your application.

In computer science, optimization is the selection of the best element (with regard to some criterion) from some set of available alternatives.

React allows us to build encapsulated components that manage their own state, then composes them to make complex UIs.

These components make up small parts of our UI. This means a lot of times we unintentionally create redundant components and structure our code in ways that can impact the overall loading time of our application.

As stated earlier, the solution is optimization, and in this case, we can describe it as the best way we can write a particular code block, function or component to achieve re-usability and reduce the time taken to return information mostly in a near instant manner.

With the help of some inbuilt APIs like React.Component, React.PureComponent and life-cycle methods React offers, we can optimize our components to ensure fast and efficient load times in our applications.

Typically, our components are composed of CSS, JS and HTML code. Being able to determine when certain pieces show up will have a great impact on your page speed.

1 - How to use React.Fragment to avoid adding extra nodes to the DOM

At some point in your application, you will need to return multiple elements. From a table list to a group of related texts you will definitely reach scenarios where you need to return a group of data.

Your code will look something like this:

// Parent.js
class Parent extends React.Component {
    render() {
        return (
            <h1>Hello there!</h1>
            <h1>Hello there again!</h1>
        )
    }
}

If you are using a linter you will see the error: JSX parent expressions must have one parent element you will be forced to wrap both elements in a parent element aka div like so:

<div>
  <h1>Hello there!</h1>
  <h1>Hello there again!</h1>
</div>

Even though everything works fine, an extra unnecessary div is created. This can lead to so many useless elements being created around our application and can also cause invalid HTML in some cases where our render data is coming from a child component in a specific order. Consider the following code:

// Table.js
class Table extends React.Component {
  render() {
    return (
      <table>
        <tr>
          <Columns />
        </tr>
      </table>
    );
  }
}

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>column one</td>
        <td>column two</td>
      </div>
    );
  }
}

The above code will render the following in our table component:

<table>
  <tr>
    <div>
      <td>column one</td>
      <td>column two</td>
    </div>
  </tr>
</table>

This is definitely not the intended output as it is an invalid HTML syntax. Fragment solves this for you. We can re-write our column component to:

// columns.js
class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>column one</td>
        <td>column two</td>
      </React.Fragment>
    );
  }
}

Now you get the intended output and even better no extra DOM node is created. This may seem small but in reality the more elements on a page the more time it will take to load. Therefore auditing pieces of your code and updating them to use fragments to group data where necessary will definitely improve your code and it’s performance. Find out more about fragments here.

2 - Use React.Suspense and React.Lazy to load components declaratively

Typically, you want to load parts of your app only when they are requested. For instance, loading shopping cart data only when the cart icon is clicked, loading images at the bottom of a long image list when the user scrolls to that point, etc.

Lazy loading is a popular optimization technique widely used to speed up the load time of applications.

React.Lazy helps us load components on demand thereby reducing the load time of our application as only the needed pieces will be present as requested.

With its simple syntax, it can be used easily without hassle. It takes a callback function as a parameter that will load the component’s file using the dynamic import() syntax.

// MyComponent.js
class MyComponent extends Component{
    render() {
        return (<div>MyComponent</div>)
    }
}
const MyComponent = React.lazy(()=>import('./MyComponent.js'))
function App() {
    return (<div><MyComponent /></div>)
}

Behind the scenes, at compile time a separate bundle is created by our webpack when it hits the React.lazy() and import() statement. This process is called Code-Splitting. Our final app will be separated into multiple bundles containing UI pieces that would be loaded whenever they are required.

3 - Use React Suspense

In the time the component will be swapped in, a small time lag will occur leaving a screen freeze experience for your user. To give the user update or feedback on the outcome of the process React.Suspense is used.

React.Suspense is used to wrap lazy components to show fallback content while loading the component.

// MyComponent.js
const Mycomponent = React.lazy(()=>import('./component.js'))
function App() {
    return (
    <div>
        <Suspense fallback={<div>loading ..</div>}>
            <MyComponent />
        </Suspense>
    </div>)
}

Now, whenever the component is being loaded and there’s a delay a fallback text *loading. . *will be rendered. Find out more about React.Suspense and .Lazy here.

4 - Prevent unnecessary re-rendering with shouldComponentUpdate()

Most times in our application, we end up having instances of one component present on the screen. For example, on a blog page, we might have different blog posts show up via a blog post component that in turn also renders like button components. If not properly managed, a change in the state of a button component can cause all of the button components to re-render. The solution to this is using shouldComponentUpdate method.

shouldComponentUpdate() is used to let React know if a component’s output is not affected by the current change in state or props. By default, it re-renders on every state change. It always returns a boolean as a response — if the component should re-render or not. The default is that it always returns true.

A shouldComponentUpdate method is called with nextProps as the first argument and nextState as the second:

shouldComponentUpdate(nextProps, nextState){
    return nextProps.next !== this.props.next  
}

Now, if the next prop hasn’t changed there’s no reason to change the appearance of the component by re-rendering. This may not seem like huge improvements, however, in an application with so many components re-rendering shouldComponentUpdate will help improve performance.

N/B: shouldComponentUpdate can cause unintended problems if you set it and forget , because your React component will not update normally. Consider using the built-in PureComponent instead of writing shouldComponentUpdate() by hand.## 5 - Use React.PureComponent

Instead of using shouldComponentUpdate method in our components, React introduced a new component with built-in shouldComponentUpdate implementation, the React.PureComponent component.

React.PureComponent is similar to React.Component. The difference between them is that React.Component doesn’t implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison.

No extra code is needed, all you need to do is to use it in your class declaration:

// use this
class MyComponent extends React.PureComponent{
    render() {
        return (<div>MyComponent</div>)
    }
}
// instead of
class MyComponent extends React.Component{
    render() {
        return (<div>MyComponent</div>)
    }
}

Now with our pure component we no longer have to write:

shouldComponentUpdate(nextProps, nextState){
    return nextProps.next !== this.props.next  
}

It already implements this by default for us.

Although this is the recommended way to use shouldComponentUpdate only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data. Find out more here.

6 - Remove unused DOM elements with ComponentDidUnmount()

When working with React it is important to think of what happens when an element is removed from the DOM. Do they really go away? Or does the code just lie around even though it is not displayed to the user?

Having unused code around causes a problem called memory leak. React solves this for us by providing us with the componentWillUnmount method.

componentWillUnmount() is used to stop any unused code from running when a component is removed from the DOM.

You can perform several cleanups with this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().

Consider the following component:

// App.js
class App extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }
    componentDidMount() {
        document.addEventListener("click", this.closeMenu);
    }
    openMenu = () => { }
    closeMenu = () => { }
    render() {
        return (
          <a href ="#" onClick = {this.closeMenu}>X</a>
        );
    }
}

In the above code, when you click the X link without the componentDidUnmount() the menu is closed but the event listener which was created when the component was mounted is still available.

To fix that, we can add a componentDidUnmount() to our component:

componentWillUnmount() {
   document.removeEventListener("click", this.closeMenu);
}

Now, when the button is clicked the event listener is removed with the *componentDidUnmount() *method.

N/B: You should not call setState() in componentWillUnmount() because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again. Learn more about it here.## 7 - Use React.Memo to cache components

One way to speed up an application is by implementing memoization.

Memoization is an optimization technique used to primarily speed up programs by storing the results of expensive function calls and returning the cached results when the same inputs occur again. A memoized function is faster because if the function is called with the same values as the previous one instead of executing function logic, it will instead fetch the result from cache.

In React, it is not uncommon for a component to change state multiple times. It is also not uncommon for some components to exist without the need to change state. If you have several components that rarely change state you should consider caching them.

React.Memo provides us with an easy API to implement memoization. It became available in React V16.6.0. Consider the following component:

// userDetails.js
const UserDetails = ({user}) =>{
    const {name, occupation} = user;
    return (
        <div>
            <h4>{name}</h4>
            <p>{occupation}</p>
        </div>
    )
}

Currently, every time the userDetails function is called it executes the function over and over again even if these details rarely change. We can use React.memo to cache it:

export default React.memo(UserDetails)

That’s all! As you can see no complex code is required. Simply wrap your component in the React.memo function and React takes care of the rest for you.

React.memo is a higher order component. It’s similar to React.PureComponent but for function components instead of classes. Find out more here.## Conclusion

In this tutorial, we explored several ways we can optimize our React components for better performance. We discussed only a few as there are lots of ways and tools used when optimizing an application.

Optimizing applications should be as needed because in some simple scenarios optimizing your components might be a killer.

One thing to keep in mind is the size and complexity of your project, would it be used for just demo or simple use cases? Or would it be deployed to be used every day by people? If the latter is the case then it may be time to think about optimizing your application.

reactjs javascript web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Why Web Development is Important for your Business

With the rapid development in technology, the old ways to do business have changed completely. A lot more advanced and developed ways are ...

Hire Dedicated eCommerce Web Developers | Top eCommerce Web Designers

Build your eCommerce project by hiring our expert eCommerce Website developers. Our Dedicated Web Designers develop powerful & robust website in a short span of time.

How long does it take to develop/build an app?

This article covers A-Z about the mobile and web app development process and answers your question on how long does it take to develop/build an app.

JavaScript developers should you be using Web Workers?

Do you think JavaScript developers should be making more use of Web Workers to shift execution off of the main thread?

Why ReactJS is better for Web Application Development?

Web Application Development is the point of contact for a business in today's digital era. It is important to choose the right platform for Web Application Development to build a high end Web