DEV Community

Cover image for useEffect in React
Amogh Nandodkar
Amogh Nandodkar

Posted on

useEffect in React

Transitioning from Classes to Functions

In class components, lifecycle methods are normally used for mounting or updating components. While working with functional components there are no lifecycle methods and useEffect hook is present which can be used for mounting or updating operations.
To start using the useEffect hook in the functional components we need to import it from react as:

import { useEffect } from 'react';
Enter fullscreen mode Exit fullscreen mode

Creating a basic side effect

In class components all the side effects are used by the lifecycle methods. This approach is fairly simple when a few side effects are involved, but when multiple side effects are involved that required to be cleaned up this approach gets confusing. With useEffect, each side effect is defined along with it's clean up in it's own useEffect hook.

The most basic side effect can be achieved by passing a single function to the useEffect. This function is the side effect you want to run.


useEffect(() => {
   console.log('This is your first side effect!')
});

Enter fullscreen mode Exit fullscreen mode

This side effect will run each time the component renders that is when the component is first mounted or when the prop or state changes. This is not ideal if the side effect is only desirable when the component mounts or when a certain state/ prop changes. For this reason the useEffect hook accepts an optional second parameter which is an array. The values of this array are compared during each re-render with the values of the array during the previous render and the side effect will only run if the values of the array differ from the ones during previous render. Hence to run the side effect on mount you need to pass an empty array as the second parameter so that the value would not change between subsequent re-renders. This can be achieved as:


useEffect(() => {
   console.log('Run side effect on mount')
},[]);

Enter fullscreen mode Exit fullscreen mode

By putting a value in the second array parameter of the useEffect hook allows the side effect to run each time the value inside the array changes. This can be achieved as:


useEffect(() => {
   console.log('Run side effect on value change')
},[value]);

Enter fullscreen mode Exit fullscreen mode

Now let us have a look at a more complex example


const [userText, setUserText] = useState("");
const handleUserKeyPress = useCallback(event => {
    const { key, keyCode } = event;
    if(keyCode === 32 || (keyCode >= 65 && keyCode <= 90)){
        setUserText(prevUserText => `${prevUserText}${key}`);
    }
}, []);

   useEffect(() => {
       window.addEventListener("keyup", handleUserKeyPress);

      }, [handleUserKeyPress]);

      return (
          <div>
              <h1>Feel free to type!</h1>
              <blockquote>{userText}</blockquote>
          </div>
  );


Enter fullscreen mode Exit fullscreen mode

Here the side effect runs each time the value of the handleUserKeyPress changes.

Cleaning the Side Effects

With the knowledge to set up the side effect, we now have to understand how to clean up the side effect. The useEffect accepts a third parameter which is a return function which runs each time the side effect runs. Using our previous example:


useEffect(() => {
   console.log('This is your first side effect!')

   return () => {
     console.log('This is your first clean up!')
   }
});

Enter fullscreen mode Exit fullscreen mode

Let us now have a look at how to implement a cleanup for our earlier window object side effect.


const [userText, setUserText] = useState("");
const handleUserKeyPress = useCallback(event => {
    const { key, keyCode } = event;
    if(keyCode === 32 || (keyCode >= 65 && keyCode <= 90)){
        setUserText(prevUserText => `${prevUserText}${key}`);
    }
}, []);

   useEffect(() => {
       window.addEventListener("keyup", handleUserKeyPress);
       return () => {
         window.removeEventListener("keydown", handleUserKeyPress);
    };

      }, [handleUserKeyPress]);

      return (
          <div>
              <h1>Feel free to type!</h1>
              <blockquote>{userText}</blockquote>
          </div>
  );


Enter fullscreen mode Exit fullscreen mode

Here the return function is the clean up function which removes the event listener.

Conclusion

The useEffect hook simplifies the side effects and clean up in components when props or state changes. In comparison to the lifecycle cycle methods in class components the useState hook helps in organizing the side effects as each side effect gets its individual hook.

Top comments (0)