Pure Components in React

Introduction 

 
In this article, we are going to discuss Pure components in React JS, what are pure functions & how to convert React components into Pure components.
 

What are Pure Functions?

 
In Javascript, when functions return the same output when the same input is passed, it is called Pure functions. It is like returning the same data for the same input. So in a pure function, the output only depends on its input arguments. Pure functions do not produce any side effects as well. In the past, you may have already created many pure functions.
 
For example:
  1. function Add(num1, num2){  
  2.   return num1 + num2;  
  3. }  
If we call the above Add(2,2) function it will always return 4 as output. So if you call the above function with the same input parameters multiple numbers of times it will always return 4 as the output. Due to this, a pure function can optimize and improve the performance of a function.
 

Pure functions in React

 
We know that in React we can create a component but in two different ways i.e one is a Class component/ Stateful component and another is Functional component/Stateless component. A React component can be considered pure if it renders the same output for the same state and props.
 
We can convert components to the pure component as below:
  1. For class components react provides React.PureComponent base class. 
  2. For Functional component react provides React.memo HOC (Higher Order Component).

React.PureComponent

 
When a class component extends React.PureComponent base class, then React treated the component as a Pure component. The major difference between the React.Component class and React.PureComponent is the implementation of shouldComponentUpdate(). In `React.Component` shouldComponentUpdate() will always return true, on the other hand in React.PureComponent it will compare the current state and props with new state and props. 
 
As React.PureComponent implements shouldComponentUpdate() method for Pure component, it improves performance and optimize rendering. However, it is only doing a shallow comparison, so if you have a very complex nested object, then it may give you a false result.
 
Let's create a simple class component, as shown below:
  1. import React, { Component } from "react";  
  2.   
  3. class PureClassComponent extends Component {  
  4.   constructor() {  
  5.     super();  
  6.     this.state = {  
  7.       name: "React JS"  
  8.     };  
  9.   }  
  10.   
  11.   changeName = () => {  
  12.     this.setState({ name: "React JS" });  
  13.   };  
  14.   
  15.   render() {  
  16.     console.log("FirstComponent -- Render method called");  
  17.     return (  
  18.       <div>  
  19.         <p> Name is : {this.state.name} </p>  
  20.         <button onClick={this.changeName}>Change Name</button>  
  21.       </div>  
  22.     );  
  23.   }  
  24. }  
  25.   
  26. export default PureClassComponent;  
In the above component, when we click on button then we are setting the same value to the name in the state. But the interesting thing is that even if we are setting the same value, it will always re-render the component.
 
 
Here, Pure components come into the picture. Pure components compare the current state with the new state and current props to new props whenever the setState() method is called. This will help reduce unnecessary calls to render() method.

Now just import PureComponent class from the react library and extend the current component with the PureComponent class and see the output in the console.
 
 
Whenever we click on the Change Name button, we are assigning the same value to state, but it is not calling the render method again and again.
 

React.memo

 
React.memo is nothing but a Higher Order function (HOC). React.memo is similar to React.PureComponent and it is for functional component instead of the class component. You can wrap your functional component when component renders the same output with the same props passed. Due to this it will improve the performance and optimize the rendering.
 
React.memo only works when props of components change. It means that if you are using state using useState hook in functional then for every state change it will render the component. Similar to React.PureComponent, it is doing a shallow comparison of props.
 
React.memo takes the first argument as a component and returns a special kind of React component.
 
For demo purposes, I have created a simple counter app, as shown below:
 
CustomLabel.js 
  1. import React from "react";  
  2.   
  3. export default ({ name }) => {  
  4.   return (  
  5.     <>  
  6.       {console.log("CustomLabel component render")}  
  7.       <label>  
  8.         <b>{name}</b>  
  9.       </label>  
  10.     </>  
  11.   );  
  12. };  
CounterComponent.js
  1. import React, { useState } from "react";  
  2. import CustomLabel from "./CustomLabel";  
  3.   
  4. const CounterComponent = () => {  
  5.   const [counter, setCounter] = useState(0);  
  6.   
  7.   return (  
  8.     <div>  
  9.       <CustomLabel name="Simple Counter app" />  
  10.       <p>Counter is : {counter} </p>  
  11.       <button onClick={() => setCounter(counter + 1)}>Click</button>  
  12.     </div>  
  13.   );  
  14. };  
  15. export default CounterComponent;  
 
Here, I have created two components i.e CounterComponent and CustomLabel component. The CustomLabel component accepts a name as a prop and displays it in a label tag. In the CustomLabel component, we have added console.log() so that we can see how many times the component is getting render. Whenever you click on the button to increase count, it will re-render the CustomLabel Component.
 
Now the 'React.memo' comes into the picture. Wrap the CustomLabel component inside the 'React.memo' HOC and test the application again. You will see it renders the CustomLabel component only once since the name prop remains the same on every button click.
 
CustomLabel.js 
  1. import React, {memo} from "react";  
  2.   
  3. const CustomLabel=({ name }) => {  
  4.   return (  
  5.     <>  
  6.       {console.log("CustomLabel component render")}  
  7.       <label>  
  8.         <b>{name}</b>  
  9.       </label>  
  10.     </>  
  11.   );  
  12. };  
  13. export default memo(CustomLabel);  
 

Conclusion

 
In this article, I have explained Pure components in React JS and also discussed how to convert Class and Functional components into Pure components.
 
I really hope that you enjoyed this article, share it with friends and please do not hesitate to send me your thoughts or comments.
 
You can follow me on twitter @sumitkharche01
 
Happy Coding!