life-cycle methods into functional components and hooks. If you started using React with the class components and are not comfortable with this transformation, this tutorial is just for you.
For sake of organization, here are the topics I will be going over.
Life-cycle methods might look a little bit trickier compared to what I’ve explained so far. We use the useEffect hook for imitating all three life-cycle methods I will be discussing here.
We use this life-cycle method for the side effects of our component, such as calling an API, etc. when the component is initially rendered. Everything inside this method is called once the initial rendering of the component is completed.
To do the same thing in a functional component, we make use of our useEffect hook. useEffect takes two parameters: the first one is a function to call, the second one is an optional dependency array.
When imitating componentDidMount, we leave the second dependency array empty. Why? Because React looks at that array and executes the function in useEffect if any value in that array changes. Since we only want to fetch our data once the component is initially rendered, we leave that array empty. An empty array means, “Hey React, watch this empty array. If anything changes, execute the function I gave you.”
Here is an important note: whether we leave the dependency array empty, pass values in it, or don’t even pass the array itself to useEffect; either way React executes the function in useEffect in the initial rendering, which brings me to the next life-cycle method.
componentDidUpdate (prevProps, prevState)
This life-cycle method is invoked after an update in props or state object occurs. It takes two parameters prevProps and prevState so we can check if the current props or state has changed in the last component update.
Now Unity is configured and ready
Here we are checking if this.props.id has changed or not. If changed, we are fetching new data based on the new id. useEffect saves us some time when checking if the props object has changed or not.
We made use of the dependency array I was talking about earlier. Now React will watch props.id value and execute the function if it changes. I want to remind again: The function in useEffect will be executed in the initial render as well as following updates on props.id while componentDidUpdate will not be executed in the initial render.
If you remove the dependency array completely, the function in useEffect will run in every update of the component.
This life-cycle method is invoked right before the component is unmounted. If you have ongoing side-effects that you started earlier such as a network request or a timer, this is the place you clean them up.
Here we created a timer in our componentDidMount life-cycle method. It updates and increases this.state.counter every second. If we do not clear this up in the componentWillUnmount life-cycle method, we will get Can’t perform a React state update on an unmounted component error after the component is unmounted.
To do the same thing in functional components, we make use of the return keyword inside our function in useEffect. Let’s create the same thing in a functional component.
In case you haven’t realized already, we did imitate componentDidMount and componentWillUnmount under one useEffect call.
Another note: Here we passed a function into setCounter method: setCounter(counter => counter + 1). This is to avoid stale closures. Dmitri Pavlutin explain what a stale closure is here very well in case you haven’t heard of it.