React — Component, PureComponent and Stateless Component
Playground
Source code & live demo app links:
- View live on Github Pages
- Check playground on CodeSandbox
Introduction
In this blog, we will focus on how these three (3) differ on when they will trigger re-render. We will not be discussing here every React’s lifecycle methods. To those who are still new to React and don’t know the basic lifecycle methods, check out React’s official documentation.
React.Component is a class component provided by React which has lifecycle methods. We can store internal state here and update it by using this.setState.
React.PureComponent has the same features with React.Component, but only re-renders when its props and state differ from previous.
Stateless Component has no lifecycle methods and does not have own state. Therefore, there is no this.setState here.
Illustration
To make it presentable, we will have a drawing like this:
Parent
We will mount the three (3) components here: Child 1, Child 2 and Child 3.
Child 1
A React class component that looks like this:
class Simple extends React.Component {
render() {
return <h1>Component</h1>
}
}
Child 2
A React class component that looks like this:
class Simple extends React.PureComponent {
render() {
return <h1>PureComponent</h1>
}
}
Child 3
A React stateless/functional component that looks like this:
const Simple = () => <h1>Stateless Component</h1>
The App
In order for us to differentiate the three (3) components, we need to have:
- state
- props
- input elements
- event handlers
- counters
Parent
- state -> name, inputValue
- props -> none
- input elements -> text input, button
- event handlers -> updateInputValue, updateName
- counters -> none
Child 1, Child 2
- state -> age
- props -> name
- input elements -> text input, button
- event handlers -> updateInputValue, updateAge
- counters -> setStateCount, renderCount
Child 3
- state -> none
- props -> name
- input elements -> none
- event handlers -> none
- counters -> renderCount
What happens …
- on initial page load?
All of three (3) components’ renderCount = 1. Why? Because they are initially created and mounted by the Parent.
- if we type “ABC” on Parent’s name input?
Child 1: no changes. Why? Because it’s props and state did not change. Take note that it only has “name” prop.
Child 2, Child 3: renderCount = 4. Why? Because every time we type something on the name input, the parent component re-renders and they also re-render.
- if we type “ABC” on Parent’s name input and hit “Update Name” once?
Child 1: renderCount = 2. Why? Because the name prop changed, so it re-renders.
Child 2, Child 3: renderCount = 5. Why? Because every time the parent component re-renders, they also re-render.
- if we type “ABC” on Parent’s name input and hit “Update Name” twice?
Child 1: renderCount = 2. Why? Because the name prop changed, only on the first click. So, the renderCount was updated only on initial mount and on first click.
Child 2, Child 3: renderCount = 6. Why? Because every time the parent component re-renders, they also re-render.
- if we type “20” on Child 1's age input ?
Child 1: setStateCount = 2 and renderCount = 3. Why? Because every time we type an age, the state “inputValue” changed, thus triggering re-render
Child 2, Child 3: no changes. Why? Because they are not affected by Child 1 on this example.
Other factors
Of course, there is an exception on how React re-renders on class-based components if shouldComponentUpdate will be implemented. In stateless component, there is React.memo. It is a higher order function that when implemented, the component behaves like React.PureComponent in its rendering logic.
Sometimes, we may encounter that there is no re-render in a React.PureComponent or React.Component since the state is being mutated. Make sure to use setState and do not mutate the state directly. React.PureComponent works by shallow compare. You can read an answer of shallow compare on stack overflow, or just search on google yourself.
Bonus
We are not limited anymore on what we can do with stateless components, since React 16.8.0 and later supports React Hooks.
Conclusion
At the end, if you know and master this very basic concept, then you will also know how to use this knowledge in a complex React app to make it optimized. Performance is important in an app and in order to achieve that, it starts in simple and basic foundation.
This is my first story on Medium. If you learnt something and enjoyed reading this content, please click the 👏 button and share to help others find this story! Feel free to leave a comment below. If you have questions and clarifications, don’t hesitate to ask me! :)