What is a React pure component?

June 2021
🔗

Definition 🤓

A component is said to be pure when given the same props, it always renders the same.
A non-pure component can, given the same props, render differently.

dice-roller.tsxTSX
import React, { FC } from 'react';

type DiceProps = {
  value: number,
};

const Dice: FC<DiceProps> = ({ value }: DiceProps) => (
  <span>
    {value}
  </span>
);

type DiceRollerProps = {
  numberOfDices: number,
};

const DiceRoller: FC<DiceRollerProps> = ({ numberOfDices }: DiceRollerProps) => (
  <>
    {Array.from({ length: numberOfDices }, () => (
      <Dice value={Math.ceil(Math.random() * 6)} />
    ))}
  </>
);

export default DiceRoller;

Two components in this example : DiceRoller and Dice.

Dice is a pure component ✅
DiceRoller is not a pure component ❌

The DiceRoller component randomly rolls new dices on each render, the only purpose of the Dice component is to render the dices. If numberOfDices equals 4, DiceRoller will roll four dices and will keep doing so everytime it re-renders. Rolling the dices with Math.random makes the result of the render unpredictable. DiceRoller is not a pure component, since given the same prop, it can render differently.
Dice, on the other hand, only renders the value it receives as prop. Given the same prop, it always renders the same, which makes it a pure component.

🔗

The purity of a component is inherent to its implementation 🧬

There is nothing wrong with a component not being pure. It just means that it needs to re-render no matter whether its props have changed or not.
Inversely, a pure component does not need to re-render if its props have not changed. This way, it can be optimized by skipping re-rendering.

🔗

Optimizing a pure component ⚡️

One way to optimize a pure component is to prevent it from re-rendering if its props have not changed*,

* To know whether the props have changed or not, React performs a shallow comparison. It means if your component receives props with complex data structures (such as nested objects), the comparison may result in a false-negative.
(cf. shallowEqual)

A class component can be optimized by creating it from the React.PureComponent base class.
A function component can be optimized by wrapping it into React.memo function.

TSX
import React, { FC, memo, PureComponent } from 'react';

export class MyClassComponent extends PureComponent {
  ...
}

export const MyFunctionComponent: FC = memo((props) => {
  ...
});
🔗

Conclusion

A React component is pure when, given the same props, it renders the same. This means the purity of a component is inherent to its implementation.
Class or function pure components can be optimized using respectively PureComponent base class or memo function.

Made with  ❤️  from Saumur