Ā« Lifecycle methods substitute with React Hooks

April 26, 2020 ā€¢ ā˜•ļø 2 min read

asset 1

Itā€™s been more than a year now since the release of Hooks. More devs are switching to Hooks implementation over classical class-based components. Even if the Hooks based implementation is difficult to understand at the beginning but itā€™s worth switching to Hooks at the end. šŸŽ‰

Before we start looking at the replacement method. Letā€™s look at the classic Lifecycle events which are used in React 16

React 16 Lifecycle Methods
React 16 Lifecycle Methods

Lifecycle Image creditsā€Šā€”ā€Šhttps://twitter.com/dceddia

Letā€™s have a look at each one of them and how it can be replaced.

componentDidMount( )

This method is usually called when the component has finished rendering for the first time. It is only called once throughout the lifecycle once after the component has finished mounting.

With Hooks:

function MyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, []); // Pass an empty array to run only callback on mount only.
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

componentDidUpdate( )

This method is called multiple times which the app lifecycle. It is invoked immediately after updating occurs. This method is not called for the initial render.

There are two ways to handle,

  1. Call hooks on every render
    As you can see if the below example the second argument in the hooks is blank meaning it will render every single time.
function MyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}); // No second argument, so run after every render.
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

2. Call hooks when specific property (dependencies) are changed
With this implementation, we need to pass the second argument to useEffect and it will be automatically triggered whenever that dependency is changed.

With Hooks:

function MyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

ComponentWillUnmount( )

As the name implies this method will be called when the component is unmounted and it will be called only once in the componentā€™s lifecycle.

With Hooks:Return a callback in useEffectā€™s callback argument and it will be called before unmounting.

function MyExample() {
const [count, setCount] = useState(0);
useEffect(() => {
// It will be called before unmounting.
return () => {
console.log('componentWillUnmount!');
};
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

shouldComponentUpdate( )

By default this lifecycle method is called every time the component is going to render where you can return true/false whenever you have to render the component or avoid rendering.

But since Hooks can be only used in functional component, and functional component internally handles the shouldComponentUpdate( ) method for use. You can already achieve this on the component level using React.PureComponent or React.memo. For preventing rerendering of the child components.

With Hooks:By default, it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.

import React from 'react'
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
const Weather = ({weather}) => {
return (<div>
<p>{weather.city}</p>
<p>{weather.temperature}</p>
{console.log('Render')}
</div>
)
}
export default React.memo(Weather, areEqual)

getDerivedStateFromProps( )

getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.

with Hooks:

function ScrollView({row}) {
const [isScrollingDown, setIsScrollingDown] = useState(false);
const [prevRow, setPrevRow] = useState(null);
if (row !== prevRow) {
// Row changed since last render. Update isScrollingDown.
setIsScrollingDown(prevRow !== null && row > prevRow);
setPrevRow(row);
}
return `Scrolling down: ${isScrollingDown}`;
}

Example referenceā€Šā€”ā€Šhttps://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops


No Lifecycle method replacement

Below are some of the methods that do not have any lifecycle method replacement for hooks according to the react documentation:

  1. componentDidCatch ( )
  2. getSnapshotBeforeUpdate( )
  3. getDerivedStateFromError ( )

Here is a quick preview of all methods together

asset 3

Thanks for reading this article. I hope you are all geared up to start replacing the classical class-based components into hooks based implementation.

Happy Learning! šŸ’» šŸ˜„

A note from JavaScript In PlainĀ English

We have launched three new publications! Show some love for our new publications by following them: AI in Plain English, UX in Plain English, Python in Plain English ā€”ā€Šthank you and keep learning!

We are also always interested in helping to promote quality content. If you have an article that you would like to submit to any of our publications, send us an email at submissions@plainenglish.io with your Medium username and we will get you added as a writer. Also let us know which publication/s you want to be added to.