Migrating to the new React Lifecycle methods
At Tubi, we use React with Redux for all our HTML5 apps. They include the evident web, both mobile & desktop, as well as our HTML5 version of OTT (Over The Top) apps. Some of the OTT platforms you can find Tubi on are Amazon Fire TV, PlayStation 3 & 4, Sony (TV & Blu-ray), Samsung TV, Opera, TiVo, plus a few others in the making. This allows us to share a lot of code between apps, while having modular abstractions in place to provide the required customization for each platform. We also make heavy use of code-splitting and bundle-splitting. To learn more about these two strategies we recommend David Gilbertson’s post on the subject.
We are big React fans. React offers us a highly declarative, modular and testable way of building our application. In addition to that, with the release of React 16, we have seen significant improvements to our application performance. In this post, we share learnings on migrating our React Component life cycle methods.
As part of v16.3.0, the React team will start the deprecation process for componentWillMount (CWM), componentWillReceiveProps (CWRP) and componentWillUpdate (CWU) methods. These methods will continue to work as-is until version 17. After that, you can continue using them under their new aliases, method name prefixed with ‘UNSAFE_’.
Currently, at Tubi, we have 30 instances of componentWillReceiveProps, 3 instances of componentWillUpdate and 2 instances of componentWillMount. Let’s explore how we are using them today and what are some migration strategies for each of these methods.
Before we dive into it, it’s worth mentioning that as part of these changes React has introduced two new lifecycle methods that could be useful. They are getDerivedStateFromProps (gDSFP) and getSnapshotBeforeUpdate (gSBU).
componentWillMount (CWM)
Perhaps the easiest of the three to migrate. The original React implementation had this method triggered only once, which means the behavior could be easily recreated by moving the logic to a constructor or in some cases, i.e. when fetching data, to componentDidMount
Use Case #1 — Fetching Data
We did not want to do this in CWM for two reasons. First, if like Tubi, you are doing server rendering the external data won’t be used. Perhaps the more dire breaking issue is the upcoming React async rendering mode which could trigger CWM more than once. The React team has blogged about this here.
So let’s take a look at an example of data fetching in our code

This is a simplified version of our CWM but it conveys the message. We are fetching the content of the featured category through a Redux action which makes an API call to our back-end. Changing this is as simple as moving it to CDM. This is an async action, and CWM will not guarantee us that it will resolve before the component mounts, so it will not have any ramifications for rendering our UI anyway. That said, we have already made sure to handle the case where we do not have the props that are fed to the component as the consequence of this call resolving (this.props.content
in our case). Here is the simplified version of the component after migrating from CWM to CDM:

Use Case #2 — Setting state
This could be setting a value to component state or instance variable. It is perhaps the less useful use case of CWM. So why were we using this lifecycle event? It used to be guaranteed that it will only be called once and we can safely call setState. That is not the case anymore, so we will just move this to our constructor
. Here are the before and after examples:

componentWillUpdate (CWU)
Before we do anything let’s see what the React team has to say about this:
Sometimes people use componentWillUpdate out of a misplaced fear that by the time componentDidUpdate fires, it is “too late” to update the state of other components. This is not the case. React ensures that any setState calls that happen during componentDidMount and componentDidUpdate are flushed before the user sees the updated UI.
Reading the above puts us at ease in just making the switch from CWU to CDU. Let’s explore a more complex example. What if the prop triggers a new async call?
componentWillReceiveProps (CWRP)
We are using CWRP a lot! This wasthe trickiest of the three to migrate, simply because it tends to grow in complexity as you try to do more with your component or pass it more props. The React team made sure we now have a new method (getDerivedStateFromProps) at our disposal to better handle some of the use cases for CWRP. See Dan Abramov’s tweet for an interesting conversation about this.
But please note that this graph is already outdated and perhaps Manual Bieh’s graph from the same thread is the one you should focus on (below).
Use Case #1 — Setting state
Again, this could be setting component state or updating an instance variable. We will focus on component state since it is the more difficult case — it causes gDSFP to run again after this.setState()
. The common pattern is to check if a certain prop has changed, and if it has, we run some logic to come up with a new value for our state. In most cases we have probably initialized the state in the constructor as seen above and in the example below, but now we want to make sure that the state stays up-to-date with the changes passed down to the component through its props.
Example: Let’s say we have a component that shows the position of the video based on a component state, which in turn is associated with video’s timeupdate
event. We will fake this using setInterval in our snippet below. We want to be able to change the position if the user decides to use the scrubber (that draggable icon to seek through video playback) and pass the position integer as a prop. We used to have a similar logic to this in our CWRP and now we have two options to move forward:

Using getDerivedStateFromProps
getDerivedStateFromProps (gDSFP) is one of those methods that has had heated debates around it and the React team discouraged its use in their post, You Probably Don’t Need Derived State. It is safe to say, use it as a last resort. gDSFP has been deliberately made into an static method in order to to reduce the risk of writing async-compatible React components, mainly by removing access to this
. See Dan’s comment below:
It [gDSFP] is invoked during the interruptible phase in async mode so mutations and side effects are unsafe there. Same as in the render method.
If you want to use gDSFP make sure to take into consideration these factors:
- gDSFP is called on new props,
setState()
andforceUpdate()
see graph below. - You will NOT have access to
this
in static methods so CWRP-like checks such asthis.props.position!== props.position
is not possible. - It is recommended to have your logic refactored into its own pure function outside of the component.
For more about gDSFP checkout React docs here and React lifecycle rfcs

Using componentDidUpdate
This approach is recommended as it is cleaner and less error prone. The rule of thumb should be use CDU unless you cannot and then and only then use gDSFP.
Live code for the CWRP, gDSFP and CDU examples. Hint: use the CodeSandBox hamburger icon and look at other files in the project
Use Case #2 — updating an instance variable or running a block of code
Remember if you want your UI to update as part of this change, you must use setState, or at very least use forceUpdate. But let’s assume you just want to make an API call for analytics purposes, or perhaps update an instance variable that is not needed for the UI.
Here is the before and after example

Summary
componentWillMount
, componentWillReceiveProps
and componentWillUpdate
will be deprecated in React v.17 under UNSAFE_componentWillMount
, UNSAFE_componentWillReceiveProps
and UNSAFE_componentWillUpdate
use at your own peril prefix. As of React v16.3 this process has already been started and new lifecycle and method have been introduced to assist with the migration.
FYI: We are hiring talented Software Engineers across all disciplines, check out our careers page if you are interested