ReactJS | useEffect Hook – GeeksforGeeks

The motivation behind the introduction of useEffect Hook is to eliminate the side-effects of using class-based components. For example, tasks like updating the DOM, fetching data from API end-points, setting up subscriptions or timers, etc can be lead to unwarranted side-effects. Since the render method is to quick to produce a side-effect one needs to use life cycle methods to observe the side effects. For example, consider updating the document title for a simple counter component to the current value. On the initial render, we set the current clicked value to 0 clicks. So, this section is coded into the componentDidMount() method which is executed only once in the component life cycle. Then we create a button to increment the count state value by one on every click. As the count value state changes, we also need to update the document title again and for that, we need to write the same piece of code in componentDidUpdate(). The componentDidupdate() method is perfect for updating the counter value at any time the state changes but the repetition of code is one of the side-effects.

Javascript




componentDidMount(){

    document.title = `you clicked ${this.state.count} times`;

}

 

componentDidUpdate(){

    document.title = `you clicked ${this.state.count} times`;

}



Let us consider another side-effect by setting up a timer. On the componentDidMount() method, we set a timer to log a string “hello” every 5 seconds. We can clear this timer when the component is being removed from the DOM. And we do that in componentWillUnmount() life-cycle method. So the code for the timer looks like below:

Javascript




componentDidMount(){

    this.interval = setInterval(this.tick, 1000)

}

 

componentWillUnmount(){

    clearInterval(this.interval)

}



Both the counter and timer when merged to form a single component looks like below:

Javascript




componentDidMount(){

    document.title = `you clicked ${this.state.count} times`;

    this.interval = setInterval(this.tick, 1000)

 

}

 

componentDidUpdate(){

    document.title = `you clicked ${this.state.count} times`;

    clearInterval(this.interval)

}



As you observe the code above, we tend to notice that to update the document title we write the same code twice, once in componentDidmount() and once in componentDidUpdate(). The second thing to observe is how the code is split into the component. The code related to the timer, setInterval, and clearInterval which are related are put into different code blocks (i.e. different life-cycle methods). The code to update the DOM and code for setting up the timer which is completely unrelated are put in the same life-cycle method (i.e. in componentDidMount()). It will be much better if there is an option to not repeat code at the same time group together related codes in the same block. This is where the useEffect Hook comes in the picture. 
The Effect Hook lets you perform side effects in functional components. It is a close replacement for componentDidMount(), componentDidUpdate() and componentWillUnmount() method.

useEffect after render: We know that, the useEffect() is used for causing side effects in functional components and it is also capable for handling componentDidMount(), componentDidUpdate() and componentWillUnmount() life-cycle methods of class based components into functional component. Let’s look at an example on how to use the useEffect hook as a feature that can mimic the above mentioned life-cycle methods but in functional components. 

For better understanding lets look how the code looks like in a class component below and we are going to name it “ClassComponentOne”

Filename: src/components/ClassCounterOne.js  

Javascript




import React, { Component } from 'react'

 

class ClassCounterOne extends Component {

    constructor(props){

        super(props)

        this.state = {

            count: 0

        }

    }

 

componentDidMount(){

    document.title = `Clicked ${this.state.count} times`

}

 

componentDidUpdate(prevProps, prevState){

    document.title = `Clicked ${this.state.count} times`

}

 

render() {

    return (

        <div>

            <button onClick = {() => this.setState(

                  { count: this.state.count + 1})}>

                Click {this.state.count} times

            </button>

        </div>

    )

}

 

export default ClassCounterOne



Now, we include the component in App.js. The code will look like below for App.js

Filename: src/App.js 

Javascript




import React from 'react'

import './App.css'

import ClassCounterOne from './components/ClassCounterOne'

 

function App(){

    return(

        <div className='App'>

        <ClassCounterOne />

        </div>

    )

}

 

export default App



Now if we look at the browser we can observe that initially the document title is “Clicked 0 times”. 

initial state

And if we click on the button the count value increments by 1 on each click and updates the title as well. 

Now let’s try to replace the functionality with a functional component. For the same purpose create a new file and name it (say, HookCounterOne.js) 

The functional component will look like the code below:

Filename: src/components/HookCounterOne.js 

Javascript




import React, { useState, useEffect } from 'react'

 

function HookCounterOne() {

    const [count, setCount] = useState(0)

 

    useEffect(() => {

        document.title = `You clicked ${count} times`

 

    return (

        <div>

            <button onClick = {() => setCount(count + 1)}>

                  Click {count} times </button>

        </div>

    )

}

export default HookCounterOne



Now we need to import the above component in our App.js file. After the inclusion of the HookCounterOne component, the code looks like below:

Filename: src/App.js 

Javascript




import React from 'react'

import './App.css'

import HookCounterOne from './components/HookCounterOne'

 

function App(){

    return(

        <div className='App'>

        <HooKCounterOne />

        </div>

    )

}

 

export default App



Now if we look into the browser we can see the initial state as below. Initially, the document title reads “You clicked 0 times”. 

And when you click on the button, the count value increments, and the document title is updated. As we can observe the behavior is as expected.  

When we specify useEffect we are basically requesting react to execute the function that we pass in the useEffect function as an argument, everytime the component renders. The second thing to make note of is that useeffect is used inside the component as by doing this we can easily access the components state and props without having to write any additional code.
 

My Personal Notes

arrow_drop_up