My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Understanding the React useEffect() Hook

Understanding the React useEffect() Hook

Bhupesh Vyas's photo
Bhupesh Vyas
·Sep 14, 2021·

5 min read

Hello everyone! Today we are going to talk about the useEffect Hook. The useEffect Hook is one of the best features of react. So, if you are excited, keep on reading, this is going to be a good one.

This post covers about useEffect hook of ReactJS. What is the uses of useEffect? What is syntax ? How does it work? When to use it ? And Some common use cases of useEffect Hook.

What is React ?

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.

What is the useEffect Hook ?

useEffect is one of the most popular Hooks because it allows you to perform side effects in function components. Let’s take a deeper look at the useEffect Hook to understand how that works.

Think of the useEffect Hook as a partial replacement for React lifecycle events. The useEffect Hook can replicate the behavior of componentDidMount, componentDidUpdate and componentWillUnmount methods.

In other words, you can respond to changes in any component that contains the useEffect Hook.

Syntax

The useEffect Hook takes two arguments:

useEffect(() => {

    // some code

  }, [someProp, someState]);

The first argument is a callback function that by default runs after every render.

The second argument is an optional Dependency array that tells the Hook to only callback if there is a change in a target state. The Hook compares the previous and current state value of each dependency.

If the two values don’t match, the Hook uses the first argument callback.

Dependency arrays override the default callback behavior and ensure the Hook ignores everything else in the component scope.

Use cases

Some common use cases of useEffect are:

  • Add an event listener for a button.
  • Data fetching from API when component mounts.
  • Perform an action when state or props change.
  • Clean up event listeners when the component unmounts.

In each case above, useEffect is used in place of a lifecycle method.

Using Dependencies Array with useEffect Hook

It’s important to use Dependency Arrays correctly to optimize your useEffect Hook. One important use of these Hooks is to prevent unnecessary re-renders even when nothing changes.

The code below prints a fetched message to the page but doesn’t use a dependency array.

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

const INITIAL_STATE = '';

const App = () => {
  const [message, setMessage] = useState(INITIAL_STATE);

  useEffect(() => {
    loadMessage();
  });

  const loadMessage = () => {
    console.log('>> Loading message <<');
    try {
      fetch('https://json.versant.digital/.netlify/functions/fake-api/message')
        .then(res => res.json())
        .then(message => {
          setMessage(message);
        });
    } catch (e) {}
  };

  console.log(`>> Current message is: ${message || 'EMPTY'} <<`);

  return <h1>{message}</h1>;
};

export default App;

This seems to be fine, but if when we open the browser console, we can see that the >> Loading Message << was rerun multiple times.

>> Current message is: EMPTY <<

>> Loading message <<

>> Current message is: Master React Hooks! <<

>> Loading message <<

>> Current message is: Master React Hooks! <<

Since the message did not change, we should optimize this to only load and fetch the message once. The secret is to add an empty dependency array. We simply replace lines 8-10 with:

useEffect(() => {

  loadMessage();

}, []);

By default, the useEffect Hook runs after each re-render. With a dependency array, it runs once then runs again whenever the passed dependency is changed. An empty array provides no condition where the Hook will run again and therefore ensures that it fetches the message on the first render only.

Run useEffect Function with Change in State or Props

We can also use populated dependency arrays to make responsive apps.

Imagine we have a React app that allows users to set a nickname using an input field. After the nickname is set, it fetches a personalized greeting message from an external API.

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

const App = () => {
  const [message, setMessage] = useState('');
  const [name, setName] = useState('');
  const [isTyping, setIsTyping] = useState(false);

  useEffect(() => {
    // We don't want to fetch message when user is typing
    // Skip effect when isTyping is true
    if (isTyping) {
      return;
    }
    loadMessage(name);
  }, [name, isTyping]);

  const loadMessage = nickName => {
    try {
      fetch(
        `https://json.versant.digital/.netlify/functions/fake-api/message/name/${nickName}`
      )
        .then(res => res.json())
        .then(message => {
          setMessage(message);
        });
    } catch (e) {}
  };

  const handleNameFormSubmit = event => {
    event.preventDefault();
    setIsTyping(false);
  };

  return (
    <div className="App">
      <form onSubmit={handleNameFormSubmit}>
        <input
          value={name}
          onChange={event => {
            setIsTyping(true);
            setName(event.target.value);
          }}
        />
        <button>Set nickname</button>
      </form>
      <h1>{message}</h1>
    </div>
  );
};

export default App;

On lines 8-15, we see that our dependency array contains name and isTyping. The useEffect runs every time there is a change in either of these states. However, you do not want to load the message until the user enters the form or clicks on the “Set nickname” button.

This is achieved with the help of the isTyping state. If isTyping is set, we return from the useEffect function and do not run it (lines 11-13).

When the user finally submits the form, reset isTyping to false. The Hook detects the change in the isTyping state and will run again. It now bypasses the if statement and this time will call the loadMessage function to initiate a fetch request.

Thats all , Hope you enjoyed and learned few things for your next big react app