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.
You can download the source code attached to this article. In the next article, we will go in details of fetching data from API and sending it to using useEffect() hook.