6 Cool Optimization Techniques In React

An important factor for better user experience is speed i.e how much time a user has to wait to first see contents from your website or application. Negative statistics lead to a decrease in user satisfaction and also eventually customers. One solution for reducing this is to properly optimize your application. In computer science, optimization is the selection of the best element (as to some criterion) from some set of available alternatives. React allows us to build encapsulated components that deal with their own state, then compose them to make complex UIs. These components make up small parts of our UI. This implies a lot of times, we unintentionally create redundant components and also structure our code in ways that can affect the general loading time of our application.

As stated before, the solution is optimization, and for this case, we can describe it as the most ideal way we can write a specific code block, function or component to achieve reusability and reduce the time taken to return data generally 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 quick and also efficient load times in our applications. Commonly, our components are composed of CSS, JS and HTML code. Being able to decide when certain pieces show up will greatly affect your page speed. Here, we will learn different optimization methods that use these inbuilt APIs, lifecycle methods and also some other general techniques that ensure you to improve your React code.

6 Cool Optimization Techniques In React-

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

Normally, you need to load parts of your application just when they are requested. For example, loading shopping cart information just when the cart symbol is clicked, loading images at the bottom of a long image list when the user looks to that point, and so on. Lazy loading is a popular optimization technique widely used to accelerate the load time of applications. React.Lazy helps us load components on demand in this way decreasing the load time of our application as just the required parts will be present as requested. 

With its basic syntax, it can be used effectively without problem. 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 made by our webpack when it hits the React.lazy() and import() statement. This process is called Code- Splitting. Our final application will be separated into different bundles containing UI pieces that would be loaded at whenever they are required.

2. Use React Suspense-

In the time the component will be swapped in, a little time lag will occur leaving a screen freeze experience for your user. To give the user update or feedback on the result 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>)
}

Presently, whatever the component is being loaded and there’s a delay a fallback text loading.. will be rendered. 

3. 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 may have different blog posts show up via a blog post component that in turn also renders like button components. If not appropriately dealt with, a change in the state of a button component can cause all of the button components to re-render. The solution for this is using shouldComponentUpdate method.

shouldComponentUpdate() is used to let React know if a component’s output isn’t influenced by the current change in state or props. By default, it re-renders on each 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 immense upgrades, however, in an application with such huge numbers of components re-rendering shouldComponentUpdate will help to improve execution.

4. Use React.PureComponent-

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

React.PureComponent is like 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 additional code is required, you should simply 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.

In spite of the fact that this is the recommended way to use shouldComponentUpdate only extend PureComponent when you hope to have basic props and state, or use forceUpdate() when you realize deep data structures have changed. Or on the other hand, think about utilizing immutable objects to facilitate quick comparisons of nested data. 

5. Remove unused DOM elements with ComponentDidUnmount()-

When working with React, it is important to consider what happens when an element is removed from the DOM. Do they truly leave? Also does the code simply lie around despite the fact that it isn’t displayed to the user? Having unused code around causes an issue 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 a few cleanups with this method, for example, invalidating timers, canceling network requests, or cleaning up any subscriptions that were made 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 yet the event listener which was created when the components was mounted is as yet 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.

6. Use React.Memo to cache components-

One approach 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 similar inputs occur again. A memoized function is faster because if the function is called with the same values from the past one instead of executing function logic, it will rather fetch the result from cache.

In React, it is common for a component to change state multiple times. It is likewise common for certain components to exist without the need to change state. If you have a few components that rarely change state you should consider caching them. React.Memo gives us a simple 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 again and again regardless of whether these details rarely change. We can use React.memo to cache it:

export default React.memo(UserDetails)

As you can see no complex code is required. Simply wrap your component in the React.memo function and React deals with the rest for you.

Apart from this, you can also know the benefits of using React for app development at- Why you should build your app with react native?

Final Words-

Speed is an important factor for web application or website’s performance as it leads to success. These optimization techniques can give you a positive effect to your react development. There can be a few others also. If you still have a question about the performance of development in react, consult with Solace experts. Solace team is here to help you with new trends and technologies that give you the best solution for your business success.