Pure Component in React

Pure Component in React

This article was originally published on the DeadSimpleChat Blog: Pure Component in React

Pure components are similar to react components but does not re-render if the props and state does not change

When a pure component receives new props and state data, it does a shallow comparison to check if the props or state data has changed.

If the data has not changed it does not re-render the component thus saving time and resources.

When re-rendering is time consuming and processing intensive it improves performance.

If you are looking for JavaScript Chat API and SDK for building chat in your app or website then DeadSimpleChat is the solution for you

What are react components

React components are like JavaScript functions. They let you split UI into different sections and think about a section of UI independently of others.

Components accept inputs called props and return react elements that display UI on the screen.

display component lifecycle methods here to increase the data

What are React functional components and React Class Components

React components can be defined as javascript functions as well as ES6 class.

React is leaning towards functional components and class components are being viewed as not best practice

Here is a basic example of react functional component

function thinkAloud(props) {
  return <h1>My name is, {props.name}</h1>;
}

This function accepts a prop (shorthand for properties) and returns a react element. Thus this is a react functional component

class thinkAloud extends React.Component {
  render() {
    return <h1>My name is, {this.props.name}</h1>;
  }
}

The function and class components both are equivalent in react's point of view.

What are Pure components in React

We have already seen what a pure component in react is in the introduction above.

To reiterate, pure components are components that do not re-render if the props and state have not changed

Pure components does a shallow check every time a new prop or state is supplied to it and skip the re-render if they have not changed thus saving precious time and resources required to re-render the component

How to use a Pure component

To use a Pure component extend the Pure component instead of the component in a class component

import {PureComponent} from 'react'

class thinkAloud extends PureComponent {
    render() {
           return <h1>My name is, {this.props.name}!</h1>;
  }
}

PureComponent is a subclass of react component and as such has all the API's of the component class

In react a component re-renders when its parent re-renders, but as an optimization you can create a component that does not re-render when its parent re-renders as long as the props and state remains the same

Class component can opt into this by extending PureComponent

Let us use some of the examples to understand PureComponent in action

import React, { PureComponent } from 'react';

class CarList extends PureComponent {
  render() {
    const { cars } = this.props;
    return (
      <ul>
        {cars.map(cars => (
          <li key={cars.id}>{cars.name}</li>
        ))}
      </ul>
    );
  }
}

export default CarList;

Here we have a list of cars in a dealership. The CarList takes an array of cars as a prop and lists the cars in an unordered list to visitors on the dealers website

The users going about exploring the website and new cars being added or subtracted is quite infrequent as the user is exploring the site

we can optimize the list of cars being displayed in a PureComponent

The CarList component only relies on the property cars which is an array of cars and does not have any additional state

1. Table Component example

Here is another example of PureComponent in react as a Table Component which renders a tab

import React, { PureComponent } from 'react';

class Cars extends PureComponent {
  render() {
    const { data } = this.props;
    return (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Company</th>
            <th>Price</th>
          </tr>
        </thead>
        <tbody>
          {data.map((car, index) => (
            <tr key={index}>
              <td>{car.name}</td>
              <td>{car.company}</td>
              <td>{car.price}</td>
            </tr>
          ))}
        </tbody>
      </table>
    );
  }
}

export default Cars;

This is a table that shows cars by their names, which car company they are from and their price

Since the Cars Component only relies on the data prop it can be extended as a PureComponent

Whenever the parent component changes the Cars component checks if the prop data has changed or not if the prop data has not been changed the Cars component does not re-render

2. Button Component example

Here is an example of a button as a pure component. The button relies on a property to change text to Next or Restart based on the parent component

import React, { PureComponent } from 'react';

class NextOrRestart extends PureComponent {
  render() {
    const { text, onClick } = this.props;
    return (
      <button onClick={onClick}>{text}</button>
    );
  }
}

export default NextOrRestart;

The NextOrRestart class component returns a button and as it only relies on a prop and has no other complex logic it can be extended as a PureComponent

The NextOrRestart checks whether the props has changed or not if the props have not changed the class does not re-render the button element

3. Chart Component example

The chart component renders its out put based on the data props. Since it does not have any other props or complex logic to depend upon. this class component can be rendered as a PureComponent

import React, { PureComponent } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';

class PureChart extends PureComponent {
  render() {
    const { data } = this.props;
    return (
      <LineChart width={600} height={300} data={data}>
        <XAxis dataKey="name" />
        <YAxis />
        <CartesianGrid strokeDasharray="3 3" />
        <Tooltip />
        <Legend />
        <Line type="monotone" dataKey="uv" stroke="#ffff" />
        <Line type="monotone" dataKey="pv" stroke="#234fghft" />
      </LineChart>
    );
  }
}

export default PureChart;

In this example the PureChart components checks whether the data prop has changed or not

of the data, prop has not changed the component does not re-render and only if the props have changed does the PureChart component re-renders

Migrating Simple Components from Class to functional

React is moving towards functional components and if you have older class components you can convert them functional components.

If you want to convert PureComponents to functional components you need the React Memo API

React Memo API

Wrap a functional component in memo to get a memoried version on that component.

This is useful when converting PureComponents which are class components to functional components

or when you want to create PureComponents as functional components

React memo API can be used like

import {memo} from 'react'

const testComponent = memo(function testComponent(props){
    //...
});

React memo API is user to avoid re-rendering when the props remain the same and as such is a performance improvement tool

React components must render pure rendering logic. It means if the props, state and context remains the same it should always render the same output

By using memo we are telling react that our component relies on this logic and react does not need to re-render the prop if these remain the same

Let us see another simple example of using memo to convert a class component to a functional component using the memo

import React, { PureComponent } from 'react';

class testComponent extends PureComponent {
  render() {
    return (
      <div>
        <h1>{this.props.name}</h1>
        <h2>{this.props.occupation}</h2>
      </div>
    );
  }
}
export default testComponent;
import React, { memo } from 'react';

const testComponent = memo(({ name, occupation }) => {
  return (
    <div>
      <h1>{name}</h1>
      <h2>{occupation}</h2>
    </div>
  );
});

Here we have converted the PureComponent which is a subset of a class component to a functional component using the react memo API

Updating the Memo component using state

When the component is memorized it will re-render when its state changes. memorization only has to do with the props that are passed on to it through its parent component

If the state variable is set to its current value the react will not re-render the component even without the memo.

import React, { PureComponent } from 'react';

class testComponent extends Component {
  state = {
    count: 0
  };

  handleClick = () => {
    this.setState(prevState => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Add</button>
      </div>
    );
  }
}

export default testComponent
import React, { useState, memo } from 'react';

const testComponent = memo(() => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Add</button>
    </div>
  );
});

This is a class component that uses state to store count. when handleclick function is called the count increases.

What happens to a memorized component when context changes

When a memorized component's context changes it will re-render. Memorized component only has to do with the props that are passed to it from its parent

let us look at an example

import React, { PureComponent } from 'react';
import MyContext from './MyContext';

class testComponent extends PureComponent {
  static contextType = MyContext;

  render() {
    return <div>{this.context.item}</div>;
  }
}

export default testComponent
import React, { useContext, memo } from 'react';
import SomeContext from './SomeContext';

const testComponent = memo(() => {
  const item = useContext(SomeContext);

  return <div>{item}</div>;
});

Note: Unlike PureComponent the memo does not compare new state with previous state.

In functional components, the set function with the same state already prevents the re-renders by default, even without the memo

Conclusion

In this article we have learned what are PureComponents, the difference between class and functional components, how to convert class components to functional components and how to convert PureComponents to functional components

we also learned about the react memo API. and what happens when state and context are used with the memo API

We also looked at a lot of examples with regard to react components and class components and functional components

I hope you have learnt from this article and that it helps you in your journey.