Introduction to useEffect Hook In ReactJS – Part Two

Introduction

In the previous article, we have learned about what is useEffect() hook is and how it is used in ReactJs.

Now, in this article continuing the previous article, we will learn about calling useEffect only once and using with along with cleanup 

useEffect() Hook to call once

In React, we know that useEffect() is called on every render, so every time any changes occur in render() function, useEffect() is called, as previously we reviewed how to call useEffect() only when changes on that event happened.

Now in some cases like the binding event to windows, we need to call useEffect() hook only once so, to do that, we will pass an empty array to useEffect(). 

Let’s look at the demo by both ways, 

First, class component to display mouse position,

import React, { Component } from 'react'  
  
class MouseClass extends Component {  
    constructor(props) {  
        super(props)  
      
        this.state = {  
             x:0,  
             y:0  
        }  
    }  
      
    componentDidMount(){  
        console.log("component Mounted")  
        window.addEventListener('mousemove',this.logMousePosition)  
    }  
  
    logMousePosition = e => {  
        this.setState({  
            x: e.clientX,  
            y: e.clientY  
        })  
    }  
  
    render() {  
        return (  
            <div>  
                X Co-ordinate: {this.state.x}, y Co-ordinate: {this.state.y}  
            </div>  
        )  
    }  
}  
  
export default MouseClass 

This will display output as below,

On moving mouse, componentDidMount() is called only once when the component is mounted.

So, in the same way, to achieve the same functionality using hook we have useEffect() hook.

Create a functional component MouseHook.js

import React,{useState,useEffect} from 'react'  
  
function MouseHook() {  
    const [x,setX] = useState(0);  
    const [y,setY] = useState(0);  
  
    const logMousePosition = e => {  
        console.log("Mouse moved")  
        setX(e.clientX)  
        setY(e.clientY)  
  
    }  
    useEffect(()=>{  
        console.log("useEffect")  
        window.addEventListener("mousemove",logMousePosition)  
    })  
  
    return (  
        <div>  
            x Co-ordinate = {x}  
            y Co-ordinate = {y}  
        </div>  
    )  
}  
  
export default MouseHook 

This will output as below.

On moving cursor, x and y coordinates are getting changed.

Now observe console, every time useEffect is also getting called which is a binding event to Windows which is totally unnecessary so to prevent it from happening, we will pass an empty array as the second parameter to useEffect() hook,

import React,{useState,useEffect} from 'react'  
  
function MouseHook() {  
    const [x,setX] = useState(0);  
    const [y,setY] = useState(0);  
  
    const logMousePosition = e => {  
        console.log("Mouse moved")  
        setX(e.clientX)  
        setY(e.clientY)  
  
    }  
    useEffect(()=>{  
        console.log("useEffect")  
        window.addEventListener("mousemove",logMousePosition)  
    },[])  
  
    return (  
        <div>  
            x Co-ordinate = {x}  
            y Co-ordinate = {y}  
        </div>  
    )  
}  
  
export default MouseHook   

Now, in the output below, we can see that only logMousePosition method is getting called.

This way we can command useEffect() hook as per our requirements. Now moving ahead, we will see how useEffect handles unmounting to prevent a memory leak.

useEffect with cleanup

As we know when using class component, we have component life cycle functions componentDidUnmount() to unmount or clean up the code. In the same way useEffect() hook provides a way to perform clean up. 

Let’s look at the demo, create a ToggleMouseHook.js,

import React, { useState, useEffect } from 'react'  
import MouseHook from './MouseHook'  
  
function ToggleMouseHook() {  
  
    const [display, setDisplay] = useState(true)  
    return (  
        <div>  
            <button onClick={() => setDisplay(!display)}>Toggle</button>  
            {display && <MouseHook/>}  
        </div>  
    )  
}  
  
export default ToggleMouseHook  

The output will be displayed like below.

Now click on Toggle button,

As we noticed that there is a console error when clicking on the toggle button, it is due to the component being hidden but it is not unmounted so useEffect() hook will be used to unmount when the container not required.

Let’s look at the demo,

import React,{useState,useEffect} from 'react'  
  
function MouseHook() {  
    const [x,setX] = useState(0);  
    const [y,setY] = useState(0);  
  
    const logMousePosition = e => {  
        console.log("Mouse moved")  
        setX(e.clientX)  
        setY(e.clientY)  
  
    }  
    useEffect(()=>{  
        console.log("useEffect")  
        window.addEventListener("mousemove",logMousePosition)  
  
        return() => {  
                console.log('useEffect hook unmounted')  
                window.removeEventListener("mousemove",logMousePosition)  
        }  
    },[])  
  
    return (  
        <div>  
            x Co-ordinate = {x}  
            y Co-ordinate = {y}  
        </div>  
    )  
}  
  
export default MouseHook  

Now the output will be displayed as below,

Summary

In this article, we have learned about useEffect() hook calling only once and how to perform cleanup with useEffect() hooks in ReactJS. 

In the next article, we will go in details of fetching data from API and sending it to using useEffect() hook. 

Any question or feedback or suggestion, please do comment and let me know.

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s