Mimic React life cycle methods with Hooks
Until somewhat recently, if you wanted to use state in React you had to use a class component extending from either
React.PureComponent. The release of React 16.8 brought hooks which allowed state to be used in functional components.
If you wanted to do something like converting an existing class component to a functional component or fetch data in a functional component, you might be wondering how we can bring over the functionality of the life cycle methods. Three of the more popular methods, namely
componentDidUpdate, can all be implemented with a single hook,
Say we have a component like this.
The example above is relatively straightforward. We fetch a list of posts once the component loads, the state with response and list them out.
If we write the same thing as a functional component.
Basically all we're doing is taking the code that was inside
componentDidMount and running it inside an effect.
The thing to remember with useEffect if that they run after each render. The second argument in
useEffect is used to control when to run the effect. The argument is an array of states which to run the effect after one of them is updated. To make sure the effect only runs once, an empty array is passed as the argument.
If you don't set the 2nd argument in a
useEffectwhere the state is updated, an infinite loop will occur.
While the above effect will run as is, React will show a warning saying that "An effect function must not return anything besides a function, which is used for clean-up." since our effect returns a Promise. To fix this, we'll move the data fetching code to an asynchronous function outside the effect.
To show how we can implement
componentWillUnmount with hooks, let's consider the following example where we create a event listener to check for the window dimensions after the component has mounted and removing the listener when the component is about to unmount.
First let's create the functional component with just the state and jsx.
Next we'll create the function used to update the states.
After that we'll create an event listener using
useEffect like we did using
componentDidMount in the class component.
Notice how we set the second argument as an empty array for
useEffect to make sure is runs only once.
Once we set up the event listener its important that we remember to remove the listener when needed to prevent any memory leaks. In the class component this was done in
componentWillUnmount. We can achieve the same thing in hooks with the cleanup functionality in
useEffect can return a function which will be run when it is time to cleanup when the component unmounts. So we can remove the listener here.
The return of
useEffect being reserved for the cleanup function is the reason why we got an error in the
componentDidMount example initially when when we made the function inside
async as it was returning a Promise.
componentDidUpdate let's look at this component.
In the above example we fetch a post once when the component mounts in
componentDidMount and then every time the id gets updated in
To get started on turning this into a functional component, let's first write the following code declaring the states and the returning jsx.
Then let's declare a function to retrieve a post.
Next we need to think about retrieving the first post when the component mounts. We can do this in a
useEffect with the second argument being an empty array.
The component should load a new post when the ID is changed. The second argument in
useEffect is a list of states for which the effect should run when once of them updates. So to run the effect again when the ID changes, we can add the ID to the array.
As you can see we can take of the both the
componentDidUpdate functionality in one
useEffect which cuts down on duplicating code.`
I hope you find this post useful on how to achieve some of the functionality in class components in functional components. If you want to learn more about hooks, the React documentation has a great introduction to hooks here.