By | November 1, 2017
1378894_bc50_2

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.

1. By default, setState triggers a re-render

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;
}

Important notes:

  1. Setting shouldComponentUpdate wrongly or forgetting that you set it can cause major problems since your component may not be updated as expected.
  2. 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 using shouldComponentUpdate. It has a very simple usage:
Perf.start()
// React operations in-between are recorded for analyses.
Perf.stop()
Perf.printWasted()

2. setState updates the local state asynchronously

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.

4. Use componentWillReceiveProps

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:

  1. React may call componentWillReceiveProps even if the props have not changed, so comparing this.props and nextProps is important.
  2. componentWillReceiveProps is invoked before a mounted component receives new props, this means React doesn’t call componentWillReceiveProps 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.


And one more thing, don’t forget to follow the OpsGenie Engineering blog to learn cool topics like Serverless, AWS, React!

Leave a Reply

Your email address will not be published. Required fields are marked *