Autoplay

    Refactor componentWillReceiveProps() to getDerivedStateFromProps() in React 16.3

    Andrew Del PreteAndrew Del Prete

    The componentWillReceiveProps() method is being deprecated in future version of React (17). Many of us use this method day-to-day to check for incoming prop changes, store state, and to invoke side effects like logging or fetching data from a server.

    In this lesson, we'll look at how to refactor an existing component that uses componentWillReceiveProps() to instead use getDerivedStateFromProps() and componentDidUpdate().

    Additional Resources: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#migrating-from-legacy-lifecycles

    Code

    Code

    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    Transcript

    Transcript

    Instructor: 00:00 with the release of React 16.3, React baked in a few new lifecycle methods along with suggestions on how to migrate from componentWillReceiveProps, which will be deprecated in future versions of React.

    00:11 In this lesson, I'm going to look at how to do that. In my code, I have a parent app component with a child component called Box and a button. When the button is clicked, it retrieves a random number between one and three and passes it to the box component. The box component is a contrived example, but it does essentially three things.

    00:31 The first thing it does is it uses the random number passed and fakes an async request to retrieve a formatted string. The fake server request function takes a number and returns a promise that resolves with a number plus itself. This is to simulate what happens you consume an API.

    00:47 The response is stored in a state property called Computed Message. This function is used in componentDidMount to retrieve an initial message and in componentWillReceiveProps to update when props change, which brings us to the second thing the box component does.

    01:02 It uses the ComponentWillReceiveProps method to watch for changes which are invoked when I click the button and updates accordingly. If the random number passed to it is equal to the previous number passed to it, then I show the message, "Same number, try again." The third thing the box component does is that it shows this little "..." loader when it's waiting for a new value.

    01:24 I set Computed Message to null and componentWillReceiveProps to display the loader until the value returns. To refactor this component away from componentWillReceiveProps, I'll have to split its functionality into two lifecycle methods. One, getDerivedStateFromProps, and two, componentDidUpdate.

    01:45 As of React 16.3, the new lifecycle method getDerivedStateFromProps was written to help with some of the new acing features they're trying to introduce in future React versions. This new method is a static and is called when the component is instantiated and when it receives new props.

    02:01 It has two arguments, next props and prove state, and expects an object return for state updates or null for no state updates, which I don't need for this example. Because getDerivedStateFromProps doesn't have a prevProps argument like componentWillReceiveProps, I'll have to work around it.

    02:17 I'll need to keep track of the previous number of props somehow so I can compare it with an incoming number of prop. I can do this by storing it in state. If the number coming in is equal to the previous number stored in state, then show the "Same number, try again," message. If it doesn't equal, then set the computed message to null and store the number for future comparisons.

    02:37 Because this method first runs when the component is instantiated, I can actually set the initial state here before first mount. However, it's probably better practice to do this in the constructor or state property above, but I'll go ahead and set it here for demonstration purposes.

    02:53 React will run this method first before mount and see that I don't have a previous state already for number and go ahead and add number to state. Now that the random number is stored in state, I have something to compare it against when a new number prop comes in. I'm going to go ahead and comment out the componentWillReceiveProps method to see where we're at.

    03:12 Now all we're doing is checking if the numbers match and either showing the "Same number, try again," message or the "..." loader. The getDerivedStateFromProps method is best for updating state based on props and is not for side effects or retrieving data from a server. To do that, the React docs recommend using componentDidUpdate, so that's what we'll use.

    03:34 I'll first check to see if the computed message is null and then go ahead and fetch a new message with fake server requests like I did before. It looks like it's working again. Depending on your use case, you may only need to refactor componentWillReceiveProps to use getDerivedStateFromProps or componentDidUpdate.

    03:55 If you need to store a state based on props, getDerivedStateFromProps is the method for you. If you need to fetch data from a server or do any type of side effects based on props, componentDidUpdate is the correct method...

    Discuss

    Discuss