I wish I knew these before diving into React
At OpsGenie, we had a deep dive into React for our Badges project. I learned many new things & made many mistakes. Some of my learnings are subjective, but I thought they may help other people to learn React and avoid making the same mistakes. Long story short, these are the things that really helped me.
setState
triggers a re-render
1. By default, The default behavior of React is to re-render on every state change, and most of the time it is okay to rely on this. However, re-rendering unnecessarily wastes cycles which is not a good practice.
Each component has a method called shouldComponentUpdate
and it is called everytime you change state or pass new props from the parent component. React decides whether to re-render or not according to the return value of shouldComponentUpdate
.
By default, shouldComponentUpdate
returns true, but you can override it to return false for cases that you do not want a re-render. Here is an example:
shouldComponentUpdate(nextProps, nextState) {
const vitalPropsChange = this.props.bar !== nextProps.bar;
const vitalStateChange = this.state.foo !== nextState.foo;
return vitalPropsChange || vitalStateChange;
}
// React will not re-render the component unless vitalPropsChange
// or vitalStateChange is true.
Important notes:
- Setting
shouldComponentUpdate
wrongly or forgetting that you set it can cause major problems since your component may not be updated as expected. - Running computations in
shouldComponentUpdate
can be expensive in terms of performance and effort, so you should make sure it is worth it. I strongly recommend you to use React’s Performance Tools to check the number of wasted cycles before and after usingshouldComponentUpdate
. It has a very simple usage:
Perf.start()
// React operations in-between are recorded for analyses.
Perf.stop()
Perf.printWasted()
setState
updates the local state asynchronously
2. You should think of setState
as a request rather than an immediate command. It is not guaranteed that the state changes are applied instantly after a setState
call.
A common mistake is to read this.state
right after calling setState
. In general, it is not reliable to use this.state
inside the setState
method.
// this.state.value is initially 0
this.setState({value: this.state.value + 1});
this.setState({value: this.state.value + 1});
this.setState({value: this.state.value + 1});
// this.state.value is 1 instead of 3
If you need to update the state based on the previous state, best practice is using the updater
function which is the first argument of setState(updater, [callback])
.
An example of passing an updater
function to setState
:
this.setState((prevState) => {
return {value: prevState.value + 1};
});
Bonus: What is the second argument, callback
?
It is an optional callback function, executed after setState
is completed and the component is re-rendered. However, componentDidUpdate
is recommended for such logic instead of callback
in the official docs.
For more detailed information I recommend you to check this part of the official document.
3. Component Lifecycle is Important!
The first step to have a happy life with React components is to understand the component life cycle. Each React component has methods that you can use to run your code at particular times in component’s lifecycle. In order to use them correctly, you should grasp the call order of lifecycle methods. We can simply divide lifecycle into three parts:
Mounting: an instance of the component is being created and inserted into the DOM.
Updating: component is being re-rendered, can be caused by changes of props or state.
Unmounting: component is being removed from the DOM.
It is very important to understand how these methods work. This post is great for understanding lifecycle methods and their usage. I also strongly recommend you to check this part of the official documents.
componentWillReceiveProps
4. Use If you want to update the state in response to props changes, this is the method you need. Compare this.props
with nextProps
and if there is a significant change, act on it.
componentWillReceiveProps(nextProps){
if(this.props.foo !== nextProps.foo){
this.whenFooChanges();
}
if(this.props.bar !== nextProps.bar){
this.whenBarChanges();
}
}
Two important notes here:
- React may call
componentWillReceiveProps
even if the props have not changed, so comparingthis.props
andnextProps
is important. componentWillReceiveProps
is invoked before a mounted component receives new props, this means React doesn’t callcomponentWillReceiveProps
with initial props during mounting.
5. Use React Developer Tools
React Developer Tools lets you inspect the React component hierarchy, components’ props and state. It is very useful in many cases because React is all about components. It exists both as a browser extension (for Chrome and Firefox), and as a standalone app.
6. Use Create React App
Facebook’s Create React App lets you create React apps with no build configuration. It is very simple to use and has a great Github readme. You only need to have Node >= 6 and it works on macOS, Windows, and Linux.
Interested in more React posts?
You learned the basics of React, now what?
How to Organize React Files Before It’s Messed Up
Originally published on the OpsGenie Engineering blog.
One thing that I learnt that is missed out here is Functional components. If you are using too many stateful components, there is something wrong with your design. Most of your components should be functional components when you use React with Redux or Mobx.
Just curious… Why repost?
https://engineering.opsgenie.com/i-wish-i-knew-these-before-diving-into-react-301e0ee2e488
I believe many React beginners can benefit from this post. So, why not share it with more people?
How about this? He wanted the codementor community to be able to read it? I never understood the mentality that if it is on one place on the interwebs it doesn’t need to be anywhere else. It makes no sense.
Thanks for the post.
I never understood the mentality that drives one to easily jump to conclusions.
I asked a question because I initially thought there may have been updates in the “new” post but wasn’t able to detect any.
Thanks for the post.