Section 8 - Lifecycle

In this section, we’ll look at a component’s lifecycle. There will be less hands-on coding and more explaining. Different lifecycle functions are called at different times throughout the lifecycle of a React component. The specific order is:

Mounting

  1. constructor(props)
  2. getDerivedStateFromProps(nextProps, prevState)
  3. componentWillMount() /*deprecated soon*/
  4. render()
  5. componentDidMount()

Updating

  1. componentWillReceiveProps(nextProps) /*deprecated soon*/
  2. getDerivedStateFromProps(nextProps, prevState)
  3. shouldComponentUpdate(nextProps, nextState)
  4. componentWillUpdate(nextProps, nextState) /*deprecated soon*/
  5. render()
  6. getSnapshotBeforeUpdate()
  7. componentDidUpdate(prevState. prevProps, snapshot)

Unmounting

  1. componentWillUnmount()

Don’t read the whole section if this is your first time learning React. The most important takeaway is that React gives you a lot of power to intercept your component’s lifecycle. For now, just  read about the constructor() and componentDidMount() functions below. You can skip everything else.

Come back to read everything if (1) you’ve finished all other sections, or (2) you’re implementing something so complex it requires you to intercept your component’s lifecycle. That day won’t be anytime soon if you are just starting out with React.

Mounting Functions

  1. constructor(props)

        

This function is called right at the beginning. Here is where you are able to initialize the state and do initial configurations. DON’T call setState in this function because there is no state to set. Use this.state = {/*your initial state object*/} instead. A constructor may look something like:

constructor(){

  // need to call super() before anything

  super();

          this.state = { value: “initial value” }

}

You must first call super() in the constructor. ES6 syntax requires that we must call the superclass’s constructor (which is super()) in a subclass’s constructor. Since our class is a subclass of React.Component (remember the class App extends React.Component syntax?), we have to call super().

Well, isn’t this identical to just writing this outside of the constructor like so?

state = {

  value: “initial value”

}

Yes. That’s why a lot of the time you don’t even need a constructor. However, there are two cases when you do want a constructor.

First, when you want to bind your functions. Remember in our previous sections, we had to bind our event handlers like so:

<button onClick={this.handleClick.bind(this)}>Submit</button>

        

This may be tedious if you need to pass handleClick() to a lot of different event listeners, and each time you have to add .bind(this) to the end of this.handleClick. So instead, you can bind your function once and be done with it forever like so:

constructor(){

  //...same as before

  this.handleClick = this.handleClick.bind(this);

}

Then, whenever you want to use handleClick(), you can just write:

<button onClick={this.handleClick}>Submit</button>

Second, in RARE occasions, you might want to initialize state based on props. So you might write something like so:

constructor(props){

  super(props);

  let content;

  if(this.props.age >= 18){

    person = “adult”

  } else {

    person = “child”

  }

          this.state = { person }

}

Notice that this time we passed props as a parameter to constructor() as well as super(). This is required if you want to access this.props.

Be careful with initializing state with based on props. Since constructor() is only called once, your state won’t be updated when your props are changed. There are two solutions to this problem. First, don’t use this pattern at all. Lift your person state up to the parent, and let the parent pass “person” to you as props. Second, use getDerivedStateFromProps(), which we will discuss below.

  1. getDerivedStateFromProps(nextProps, prevState)

This function is called (1) after the component is created, or (2) when it receives new props, or (3) when the parent of this component forces this component to re-render. This function should return an object, which will be used to update state, or null, which means that an update to state is not needed. This is where you can change the component’s state according to the props received.

  1. componentWillMount()

// deprecated soon, use componentDidMount() instead

This function is called once before the component is mounted. Here you are able to access this.props and this.state, so you may do initial configurations here. We could do something like:

componentWillMount(){

  if(this.props.age >= 18){

    this.setState({ person: “child” });

  } else {

    this.setState({ person: “adult” });

  }

}

However, this is not common because you can do the same thing in constructor(). Another use of the function is to subscribe to events, such as a Flux store. This is out of the syllabus of this course. Generally componentWillMount() is not commonly used, so don’t worry about it too much.

  1. render()

        

You should already be very familiar with our dear friend - render(). Here is where you can access this.props, this.state as well as all other functions you defined yourself. This function returns a JSX for React to render.

  1. componentDidMount()

This function is called once when our component and its children components are all mounted. Here is when you want to perform actions that require a mounted component, such as starting network requests for API calls, performing actions on DOM nodes and subscribing to events. If you are subscribing to events here, remember to unsubscribe to them in componentWillUnmount().

Updating Functions

  1. componentWillReceiveProps(nextProps)

// deprecated soon, use getDerivedStateFromProps() instead

This function is called when your component is passed new props. This function may also be called when props is NOT changed, so be careful. The most common use case for the function is to update the component’s state based on the props. Continuing on our previous example, we can write something like:

componentWillReceiveProps(nextProps){

  let content;

  if(nextProps.age >= 18){

    person = “child”;

  } else {

    person = “adult”;

  }

  // create state

  this.setState({person});

}

  1. getDerivedStateFromProps(nextProps, prevState)

        

        Same as above

  1. shouldComponentUpdate(nextProps, nextState)

        

This function is called when new props or state are received. DON’T cause any side-effects, such as calling setState, here. This function should return a boolean value indicating whether the component should re-render or not. The function returns true by default, meaning the component always re-renders. Generally you won’t ever have to touch this function, but it is useful if you are a React ninja and want to optimize your application’s performance.

Note that in the future returning false may still results in a re-rendering of the component. Check for the most up-to-date document before using this function.

  1. componentWillUpdate(nextProps, nextState)

// deprecated soon, use componentDidUpdate() instead

This function is called before the component is re-rendered (i.e. after shouldComponentUpdate() returns true). DON’T call setState in this function. Functionally, it is similar to componentWillMount(). You may compare this.props with nextProps and this.state with nextState and if needed, perform actions based on the information.

  1. render()

        

Same as above.

  1. getSnapshotBeforeUpdate(prevProps, prevState)

Now our component is rendered, but not yet committed to the browser’s DOM. Here you can capture any values of the DOM (e.g. scroll position) before they are potentially changed. Anything returned from this function will be passed as the snapshot parameter to the componentDidUpdate() function.

  1. componentDidUpdate(prevState. prevProps, snapshot)

Here you can do the same things in componentDidMount(). The snapshot parameter is whatever value returned by getSnapshotBeforeUpdate(), otherwise it is undefined.

Unmounting Function

  1. componentWillUnmount()

It’s sad, but your component has to go. This function is called before your component unmounts (dies). Here is where you want to clean up any resources you might have used, such as any event listeners, outgoing network requests and 3rd party UI library elements.

Summary

You’ve made it here. I’m proud of you. Seriously. I guess the only thing to summarize is the fact that you have all these lifecycle functions at your disposal. Be well-informed and cautious when using them as they can lead to hard-to-find bugs.

This section is last updated on 18 May, 2018. If you’re reading this way in the future (hello from the past!), please check the offical React documents to see if anything significant has changed.