Lifecycle Methods

Class-based components have the following five lifecycle methods:

  1. componentWillMount
  2. componentDidMount
  3. componentWillUpdate
  4. componentDidUpdate
  5. componentWillUnmount

As of version 2.1.0, you can also use lifecycle hooks with functional components. Check the documentation to learn more.

Lifecycle methods are hooks that let you implement maintenance, register or remove events, and other clean based on the status of a component from when it is created and injected into the DOM, when it is updated and when it is removed from the DOM.

componentWillMount is executed before the component is created and inserted into the DOM. As such, it will always fire, whether the mount was successful or not. If you need to access the DOM, set up an event, or make a network request for remote resources, use the componentDidMount hook.

This lifecycle hook receives a callback named done. You need to call this after doing whatever you need to do before the component is updates. If you fail to call done(), the update will not complete. Mounting is triggered by a component's state, so this is not the place to get data to set on a component. Get the data first and then set the component's state.

componentWillMount(done) {
  // Do whatever you need to here...
  // Delay mounting by 3 seconds
  setTimeout(() => {
    // Don't forget to call done:
    done()
  }, 3000)
}

componentDidMount is executed after the component is inserted into the DOM. This is the place to set up events, access the child nodes of the component, or make a request for remote resources over the network. The callback gets passed a reference to the component instance as its argument. Using this, you can use this.element to access the component instance DOM tree.

componentDidMount() {
  // Access the component instance root element:
  this.element.addEventListener('click', this)
  this.input = this.element.querySelector('input')
}

componentWillUpdate is executed right before the component is updated. It will not execute if the component is not yet mounted. Because this is async, the component will probably update before this finishes executing. It's best to instead use componentDidUpdate for reliability. Otherwise, do whatever you need to do before the update and use a promise to update it.

componentWillUpdate will execute when Composi tries to update a component. If a component is updated with the same data as previously, no update will occur and this will not execute. You can access this.element, this.props and this.state from within the componentWillUpdate callback. This lifecycle hook receives a callback named done. You need to call this after doing whatever you need to do before the component is updates. If you fail to call done(), the update will not complete. Here is how to use it. Failing to call done() in componentDidUpdate means that the component will be out of sync with its state.

In the following example we delay the update of the component for 3 seconds:

import { h, Component } from 'composi'
class Title extends Component {
  render(data) {
    return (
      <nav>
          <h1>
          </h1>
      </nav>
    )
  }
  // Pass in the done callback to complete the update:
  componentWillUpdate(done) {
    console.log('Getting ready to update!')
    // Do whatever you need to do before updating...

    // Delay update for 3 seconds:
    setTimeout(() => {
      console.log('We are now updating!') 
      // Don't forget to call done!
      done()
    }, 3000)
  }
}

componentDidUpdate is executed immediately after the component is updated. If a component is updated with the same data as previously, no update will occur and this will not execute. You can use this lifecycle hook to examine the component instance element, props and state like with componentWillUpdate. Be aware that this.props never changes as it is the value assigned when the component was instantiated.

componentWillUnmount is executed before a component is unmounted with its unmounted method. This receives a callback named done. You need to call this after doing whatever you need to do before the component is unmounted. If you fail to call done(), unmounting will not complete. Here is how to use it. Notice how we delay the removal of the component for 5 seconds:

import { h, Component } from 'composi'
class Title extends Component {
  render(data) {
    return (
      <nav>
         <h1>
         </h1>
      </nav>
    )
  } 
  // Pass in the done callback to complete the unmounting:
  componentWillUnmount(done) {
    console.log('Getting ready to unmount!')
    // Do whatever you need to do before unmounting...

    // Delay unmount for 5 seconds:
    setTimeout(() => {
      console.log('We are now unmounting!')
      // Don't forget to call done!
      done()
    }, 5000)
  }
}
          

Notice: If you do not call the done callback as in the above example, the component will never unmount.

Difference between Will and Did

The three lifecycle hooks with Will in their names allow you to delay they action until you are ready. This is done with the done callback. If you are using componentWillMount, componentWillUpdate or componentWillUnmount you have to pass them the done callback:

componentWillMount(done) {
  // Do whatever you need to here...
  // Let the mount happen:
  done()
}
componentWillUpdate(done) {
  // Do whatever you need to here...
  // Let the update happen:
  done()
}
componentWillUnmount(done) {
  // Do whatever you need to here...
  // Let the unmount happen:
  done()
}

In contrast, componentDidMount and componentDidUpdate execute immediately.

Order of Execution

The first time a component is rendered, componentWillMount and componentDidMount will be executed. componentWillUpdate and componentWillUpdate will not be executed at this time. After the component is created, each render will fire componentWillUpdate and componentDidUpdate. So, if you want to do something when the component is initially created and after it updates, you would need to do this:

class List extends Component {
  //... setup here.
  componentDidMount() {
    // Do stuff right after the component mounts.
    // This will run only once.
  }
  componentDidUpdate() {
    // Do stuff every time component is updated.
    // This will start with the first update after mounting.
  }
}

Accessing the Component Instance in Lifecycle Methods

When we create a new component by extending the Component class, we can access component properties directly through the `this` keyword. This is so because we define the lifecycle methods as class methods. Notice how we do this in the example below.

See the Pen Composi lifecycle-2 by Robert Biggs (@rbiggs) on CodePen.