"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

Having trouble accessing a React component class from a different component class

I just started learning reactjs and javascript. For a simple project, I'm working on creating a login and registration form. The issue I'm facing is that when a user enters their email and password and clicks 'register', instead of movi ...

I experienced an issue with Firestore where updating just one data field in a document caused all the other data to be wiped out and replaced with empty Strings

When updating data in my Firestore document, I find myself inputting each individual piece of data. If I try to edit the tag number, it ends up overwriting the contract number with an empty string, and vice versa. This issue seems to stem from the way th ...

Concealing the rear navigation button within the material carousel

I have a material css carousel, and I am trying to hide the back button on the first slide. I attempted to use the code below from a previous post The following code snippet prevents the user from looping through the carousel indefinitely. Stop looping i ...

Is your jQuery .on function failing to properly detect click events?

Seems like I'm missing something here. Why is the .on function not functioning as expected in this code snippet? <html> <head> </head> <body> <button type="button" class="close" data-test="test">TEST BUTTON< ...

Implementing dynamic component swapping in Vue 3 using components from another component

I currently have a display component called app-display, which contains a dynamic component inside (by default, it is set to app-empty): app.component('appDisplay', { template: `<component :is="currentComponent"></c ...

Patience is key when it comes to waiting for a function to finish before moving on to the next step

I'm delving into the world of node js and currently immersing myself in the concepts of promises and async/await. Here's a code snippet I've been experimenting with, but I can't quite figure out how to ensure that the code waits until t ...

Encountered a Dojo error of "TypeError {stack: (...), message: "undefined is not a function"}" when attempting to display a gif during an ajax load

I've been attempting to display a loading gif while an ajax call is in progress. However, I encountered an error at the show statement and the console displayed: TypeError {stack: (...), message: "undefined is not a function"} Here's my code sn ...

Tips for detecting a new day with server-side JavaScript

I am currently developing a website that includes a schedule for teachers. I have encountered the need to delete elapsed days data from a database. What is the most effective method to monitor when it is exactly 12 midnight? If I were to use setInterval( ...

Redirecting with Express js when the cookie is not found

I successfully integrated Facebook login using Passport-js and also set up Cookie-strategy for traditional username/password login on my Express-js backend with a React front-end. The backend and frontend are hosted on separate servers and domains (backend ...

When attempting to render a base64 string in an <img> tag using ReactJS, an error message ERR_INVALID_URL is displayed

I am currently working on displaying server-generated images (specifically matplotlib graphs) in a ReactJS module without needing to save the files on the server. To achieve this, I decided to use base64 to create an image string. When it comes time to sh ...

executing several asynchronous requests upon loading the webpage in a single-page application

As a newcomer to front end development, I have a question about page rendering performance. In my single page application, I have utilized multiple Ajax calls to retrieve data for manipulation in order to enhance performance. However, I am concerned that ...

How can I convert an object array back into an iterated collection after using the find() method in MongoDB?

Currently, I am working on developing an application using AngularJS, NodeJS, and MongoDB. My goal is to load Products classified by ProductCategoryCode sent from AngularJS to NodeJS. The process involves finding Products based on ProductCategoryCode, iter ...

Why is it that a JSX element can take a method with parentheses or without as its child?

Why is it that when I attempt to pass a method without parentheses into a React component as a child of one of the JSX elements, an error appears in the console? However, simply adding parentheses resolves the issue. What's the deal? For example: ran ...

Error: Unable to interpret the URL provided in /api/posts/1

When working on my next.js 13 app, I encountered an issue while trying to fetch individual blog data from a local MySQL database. In the src/blog/[id]/page.js file, I have the following component: const BlogPost = async ({ params }) => { const data ...

What steps are necessary to create an npm package utilizing three.js without any dependencies?

I have a challenge - I am trying to create an npm package that generates procedural objects for three.js. The issue I'm facing is how to properly include three.js in my code. I attempted to establish a dependency and use something like const THREE = r ...

Automating button clicks after a component has loaded in Angular 2+ can be achieved by implementing a

Currently, I am working on implementing an automatic search function in Angular that triggers after a component loads. Right now, the function is triggered by a button click, but I want to automate this process. <button mat-raised-button class="mat-whi ...

Sending information from the parent component to the child Bootstrap Modal in Angular 6

As a newcomer to Angular 6, I am facing challenges with passing data between components. I am trying to launch a child component bootstrap modal from the parent modal and need to pass a string parameter to the child modal component. Additionally, I want t ...

Capturing numerous data points with JavaScript

<span> <label class="label">Color</label> <span class="foo"><input name="Color" value="Blue" class="customs" maxlength="100" type="text"/></span> </span> </span> <span> <label cla ...

Tips for expanding the content of a blogger page to fill the entire frame of the page

Check out this page: . Currently, the video on the page does not fill up the entire screen. Any suggestions for a solution? ...

What is the method for altering the date format of a published article?

I am looking to modify the date format of a published post in WordPress. Currently, the date format is <?php the_time('m.d.y'); ?></div>, which appears as "1.20.2018". My goal is to change it to "January 20, 2018". Can anyone guide ...