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.