"Why does the useEffect in Next.js fire each time I navigate to a new route

Currently, I have implemented a useEffect function within the Layout component. This function is responsible for fetching my userData and storing it in the redux-store. However, I have noticed that this function gets triggered every time there is a route change.

I would like the useEffect function to only run the first time and avoid triggering again when the routes are changed. This continuous triggering is resulting in unnecessary requests being sent to the server. How can I prevent this from happening?

Below is the code snippet of my Layout component:

import { useEffect, useState } from "react";
import Navbar from "../navbar/navbar";
import Footer from "../footer/footer";
import Head from "next/head";
import { useCookies } from "react-cookie";
import { useDispatch, useSelector } from "react-redux";
import axios from "axios";
import { getUserData } from "../../redux/actions/Auth";

const Layout = ({ children }) => {
  const [cookie, setCookie] = useCookies(["token"]);
  const dispatch = useDispatch();

  useEffect(() => { // Issue: useEffect triggers on each route change
    const { token } = cookie;
    if (token) {
      axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
      dispatch({ type: "IS_LOGGED_IN" });
      dispatch(getUserData(token));
    }
  }, []);

  return (
    <div className="layout" dir="rtl">
      <Head>
        <meta name="description" content="" />
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link
          rel="preconnect"
          href="https://fonts.gstatic.com"
          crossOrigin="true"
        />
        <link
          href="https://fonts.googleapis.com/css2?family=Noto+Kufi+Arabic:wght@100;200;300;400;500;600;700;800;900&display=swap"
          rel="stylesheet"
        />
        <link
          rel="stylesheet"
          type="text/css"
          charset="UTF-8"
          href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css"
        />
        <link
          rel="stylesheet"
          type="text/css"
          href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css"
        />
      </Head>
      <Navbar />
      {children}
      <Footer />
    </div>
  );
};

export default Layout;

Answer №1

The Issue:

Using the useEffect hook in a way that triggers on component mount and with every route change, which is the expected behavior when used in the Layout component.

Possible Solutions:

To address this issue, one solution is to implement the getUserData(token) function in a parent component of Layer, which remains unaffected by route changes.

Another approach involves using a separate state variable to manage the API call status. If you have an IS_LOGGED_IN action that alters your reducer, consider updating it as follows:

case IS_LOGGED_IN:
  return {
    ...state,
    isUserLoggedIn: true
  }

Subsequently, ensure to check the value of this property within the useEffect before dispatching getUserData:

const isLoggedIn = useSelector(state => state.user.isUserLoggedIn) // Retrieve isUserLoggedIn from the state

useEffect(() => { 
    if (!isLoggedIn) {  // -----> Call getUserData if the user is not logged in

      const {token} = cookie;     
      if (token) {
        axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
        dispatch({ type: "IS_LOGGED_IN" });
        dispatch(getUserData(token));
      }
    }
  }, [isLoggedIn]);

Insight:

Upon utilizing the Layout component, the initial value of isLoggedIn is false (reflecting the user's non-logged-in state), prompting the execution of dispatch(getUserData(token)) to fetch data. Subsequently, once isLoggedIn changes to true, the conditional statement inside the useEffect prevents further invocation of getUserData.

Note: It may be necessary to introduce another action in the reducer to effectively toggle between the user being logged in or out within the application.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

utilizing javascript function in Icefaces applications

I'm facing an issue. Here's the situation: I'm working on a quiz game where I need to implement a timer using JavaScript (jquery.timer.js). I have created a JavaScript file (question.js) with a method called startTimer, which utilizes the jq ...

Step-by-step guide on redirecting to a different page in NextJS if a dynamic route cannot be found

I need assistance with redirecting users when they access a dynamic route that does not exist. The dynamic route points to a field within a statically defined array of fields. Here is the code snippet for the page: import { fields } from "@/data/fiel ...

AngularJS synchronous $resource functionality allows for the ability to make parallel API

I'm facing a dilemma because I understand that Javascript isn't designed for synchronous work, especially in the case of AngularJS. However, I find myself in a situation where I require it. The main page on the "www" domain (built with AngularJS ...

Show users who liked a post from 2 different collections in Meteor

How do I retrieve a list of users who have "liked" this post from a collection and display it in a template? Collections: likes: { "_id": 1234, "userId": "1dsaf8sd2", "postId": "123445" }, { "_id": 1235, "userId": "23f4g4e4", "pos ...

JavaScript slowness

Currently, I am developing a test page that consists of buttons triggering various scripts. One of the functionalities I am trying to implement is changing the background color every second for 5 seconds, cycling through a total of 5 different colors. Desp ...

Error: X does not conform to function definition

I'm currently in the process of developing a Vue application that interacts with Spotify's API to search for tracks. However, I've encountered an issue where I receive the following error message: Uncaught (in promise) TypeError: searchTra ...

Guide to showcasing images dynamically within a table

I am currently working on a dynamic table that updates its data using a script. My goal is to also display corresponding images of the groups next to their names in the table. Whenever the group names change, I want the images to change as well. The funct ...

Purge all previous page visits within a specified domain upon user logout using JavaScript

On my website, abc.xyz.com, an individual named A logs in from the login page and is directed to the home page. Then, when user A clicks on the profile button, they are taken to a page displaying their information. User A logs out, prompting the site to ...

An Ajax call nested within another Ajax call

I've implemented an AJAX request to load my "home" page and "about" page into a designated "container" when a menu link button is clicked on my index.php. Now, I have three links on my "home" page and I want each of these links to open within the same ...

How can I manage file input within a Vue.js application?

After attempting to open a file input with a button, I encountered an issue. When clicking the button, the client reported: “this.$refs.image.click”. Below is my code snippet: <v-btn height="50" ...

Toggle jQuery to hide a div and update its CSS styling

There is an anchor with the class of "hide-btn1" that I want to trigger a series of actions when clicked: The rcol-content should hide and the text should change from Hide to Show The #container width needs to increase to 2038px The table.status-table wi ...

Implementing AJAX requests in jQuery DataTable with ASP.NET MVC

For some time now, I have been using the jQuery DataTables 1.10.13 plugin. Recently, I encountered an issue related to the ajax data source for my HTML table. This is how I initialized jQuery DataTable inside Files.cshtml <script language="javascript" ...

Guide on Importing All Functions from a Custom Javascript File

As a beginner in learning Angular, I am faced with the task of converting a template into Angular. However, I am struggling to find a solution for importing all functions from a custom js file into my .component.ts file at once. I have already attempted t ...

Having issues with Thymeleaf template not functioning properly when using inline JavaScript

I've encountered an issue when attempting to extract my function into a script within HTML. When written as shown below, it works perfectly: <input type="text" id="myInput" onkeypress="return confirm('Are you sure you want to delete ...

What is the process for integrating an autoplay script into Turn.Js?

Can someone guide me on how to implement this code in Turn.Js? setInterval(function() { $('#flipbook').turn('next'); }, 1000); ...

Is it necessary to include a promise in the test when utilizing Chai as Promised?

Documentation provided by Chai as Promised indicates the following: Note: when using promise assertions, either return the promise or notify(done) must be used. Examples from the site demonstrate this concept: return doSomethingAsync().should.eventua ...

Using Angular as a template engine: A simple guide

My goal is to utilize Angular as a template engine and then pass the resulting HTML code to another library. In my template file named template.html: <div><h1><span data-ng-show="details.rs">{{details.rs}}</span></h1></di ...

Include category to the smallest element

I am attempting to use JQuery to find the height of the tallest element and then add that height to other elements that are shorter. My goal is to assign the class, main-nav-special-padding, to these shorter elements using my current JQuery code. I tried t ...

"Attempting to use a Chrome Extension to apply inline styles is not producing

Despite my attempts to search on Google, I have been unable to find a solution. I am currently working on developing a Chrome extension with the specific goal of changing/inserting the style.display property for one or more elements. This task would norma ...

Angular JS Troubleshooting: Application Not Functioning Properly

I've been learning AngularJS on codeSchool and I ran into an issue with my simple hello world app. It was working fine at first but then stopped completely. I can't seem to find the bug, so any help would be appreciated. Here is the HTML code: & ...