What causes the useEffect hook to render twice in a Next.js application?

Within my Next.js application, I am seeking a way to verify whether a user has permission to access a particular page. While using a context, I encountered an issue where my useEffect hook was returning both the updated and default values. How can I ensure only the most recent value is returned?

Here is the guard page I have implemented:

"use client";
import React, { createContext, useState, useEffect} from "react";
import { tokenServices } from "./services";
import { usePathname } from "next/navigation";

type JWTContextType = {
  isAuthenticated: boolean;
};

const AuthContext = createContext<JWTContextType>({
  isAuthenticated: false,
});

const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const hasAccess = tokenServices.getToken();
  const pathname = usePathname();
  useEffect(() => {
    if (hasAccess) {
      setIsAuthenticated(true);
    } else if (!hasAccess) {
      setIsAuthenticated(false);
    }
  }, [pathname, hasAccess]);
  return (
    <AuthContext.Provider value={{ isAuthenticated }}>
      <>{children}</>
    </AuthContext.Provider>
  );
};
export { AuthContext, AuthProvider };

Here is the layout page I am using:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { AuthProvider } from "./GuestGuard";
import { ProtectedRoutes } from "./protectedRoutes";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
  manifest: "/manifest.json",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <AuthProvider>
        <ProtectedRoutes>
          <body className={inter.className}>{children}</body>
        </ProtectedRoutes>
      </AuthProvider>
    </html>
  );
}

My expectation is that the useEffect hook should only return a single value.

Answer №1

Recently, in my new guard page, I encountered an issue with my useEffect hook where it only returned the updated value when I set the initial value of isAuthenticated to undefined. I noticed that my useEffect was rendering multiple times, even though the code seemed simple. It was frustrating to see the condition inside useEffect being evaluated multiple times.

"use client";
import React, { createContext, useState, useEffect } from "react";
import { tokenServices } from "./services";
import { usePathname } from "next/navigation";

type JWTContextType = {
  isAuthenticated: boolean | undefined;
  isLoading: boolean;
};

const AuthContext = createContext<JWTContextType>({
  isAuthenticated: false,
  isLoading: true,
});

const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const [isAuthenticated, setIsAuthenticated] = useState<boolean | undefined>();
  const hasAccess = tokenServices.getToken();
  const pathname = usePathname();
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    setIsAuthenticated(!!hasAccess);
    setIsLoading(false);
  }, [isAuthenticated, pathname]);

  if (isLoading) {
    return <div>Loading...</div>;
  }

  return (
    <AuthContext.Provider
      value={{ isAuthenticated: isAuthenticated, isLoading }}
    >
      <>{isAuthenticated !== undefined && children}</>
    </AuthContext.Provider>
  );
};

export { AuthContext, AuthProvider };
This is the new layout design:
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { AuthProvider } from "./AuthGuard";
import { ProtectedRoutes } from "./protectedRoutes";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
  manifest: "/manifest.json",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AuthProvider>
          <ProtectedRoutes>{children}</ProtectedRoutes>
        </AuthProvider>
      </body>
    </html>
  );
}

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

A guide to effectively utilizing a TypeScript cast in JSX/TSX components

When trying to cast TypeScript in a .tsx file, the compiler automatically interprets it as JSX. For example: (<HtmlInputElement> event.target).value You will receive an error message stating that: JSX element type 'HtmlInputElement' is ...

Ways to configure my react frontend to communicate with my nextjs backend

My current setup consists of a React frontend running on localhost:3001 and a Next.js backend running on localhost:3000. I have a REST endpoint at /api/employee, and I'm attempting to fetch data from my frontend using the following code: fetch(process ...

Angular Tutorial: Understanding the Difference Between TypeScript's Colon and Equal To

I've been diving into the Angular4 tutorial examples to learn more about it. https://angular.io/docs/ts/latest/tutorial/toh-pt1.html One of the code snippets from the tutorial is as follows: import { Component } from '@angular/core'; @Co ...

Error in AngularFire2 typings: The property 'take' is not present in the type 'FirebaseObjectObservable<any>'

Recently, I upgraded my ionic app from beta 11 to rc0, which also involved transitioning from typescript 1.8 to version 2. After following the configuration steps for AngularFire2 on the site Getting Started with Ionic 2 RC0, Firebase 3 + AngularFire 2, I ...

How to Use an Object Created from a Different Class in TypeScript

Scenario In the development process, I am using an auth.service.ts. This service is responsible for fetching user information from the database upon login. The retrieved data is then used to create a new user object. Here is a snippet of the code: user: ...

When using React Hooks, the useEffect hook with a dependency can cause the initial image to render instead of the desired

I am currently utilizing the React Hook useEffect to assist in establishing a default image for an image loading component that loads a user's avatar on their profile page. However, due to the layout structure of Semantic-UI-React, there appears to be ...

The console log is not being displayed in my Redux reducer and it is returning an undefined

I'm facing an issue with my Redux application after integrating JWT into my Nest API. Below is the code snippet from my reducer: export default function reducer(state = {}, action) { switch (action.type) { case 'USER_LOGIN_SUCCESS&apo ...

Solving the issue of interconnected promises in Angular services

I am utilizing a DynamoDB service within my Angular project which returns a promise through a series of promises. This process involves retrieving a subId from Cognito and then passing that subId to a DynamoDB get query: async getUserObject(): Promise< ...

Is it possible to evaluate a conditional in Angular after retrieving values from a subscription in an observable?

Objective: Verify conditional statement after retrieving data from an array Attempts Made: I explored various articles on SO with similar queries, but they didn't quite match my situation. I need to ensure that the entire Array is populated before ev ...

Ways to implement functional component in ReactJs

I am currently working with Reactjs and utilizing the Nextjs framework. In my project, I am attempting to retrieve data from a database using Nextjs. However, I am encountering an error that states "TypeError: Cannot read property 'id' of undefin ...

What is the best method for storing numerical data for a Next.js/React website? Should you use a CSV file, make a backend API call, or download

I'm working on a nextjs website and I want to integrate a chart. Where would be the best place to store the data for this chart? Here are some options I've considered: Save a csv file in the public folder and retrieve it from there Store a csv f ...

The 'job' field is not recognized within the 'PrismaClient' type, please check the documentation for correct usage

Currently, I am utilizing Expressjs as a backend along with Prisma for database management and TypeScript implementation. I have been referencing this specific article in my development process. A type error that I am encountering is stated as Property &a ...

What steps can be taken to address the InvalidPipeArgument error when working with dates?

When attempting to format a date in a specific way using the pipe date, I encountered an error: Uncaught Error: InvalidPipeArgument: 'Unable to convert "25/01/2019" into a date' for pipe 'e' at Xe (main.fc4242d58c261cf678ad.js:1) ...

Using typescript with create-react-app - organizing types in a separate file

I'm currently developing a project using Create React App with TypeScript (create-react-app myapp --typescript) In my App.tsx file, I have written some TypeScript code that I want to move to an external file. I have tried creating App.d.ts, index.d.t ...

The argument of type 'NextRouter' cannot be assigned to the parameter of type 'Props' in this scenario

In my component, I am initializing a Formik form by calling a function and passing the next/router object. This is how it looks: export default function Reset() { const router = useRouter(); const formik = useFormik(RecoverForm(router)); return ( ...

Exploring the concept of the never type in TypeScript 2

Exploring the latest features in TypeScript 2.0, I came across the never type. It appears to be a clever method for defining the type of functions that do not have a return value. If I understand correctly, the never type can be assigned to any other type ...

Tips for incorporating buttons into columns on ng2-table within Angular 2

I am in need of a table with an edit button in every column using ng2. However, I have encountered an issue placing the buttons at the end of each column. Here is my HTML code: <ng-table [config]="config.sorting" (tableChanged)="onChangeTable(co ...

The error message "Module not found tsconfig.json in NextJS Bazel 7" may

Currently, I am in the process of bazelifying a NextJS project based on the app router example project. To achieve this, I am utilizing the ts_project macro as per the guidelines provided in this rule. Everything seems to be working smoothly, except for th ...

Encountering an error while trying to implement strong typing in a function on a Node API service: 'Unexpected token ":"'

I've developed a TypeScript Node API service and here's a snippet of my code: class dataStreamConfig { constructor() { } conclaveObj = (firstParam: string, secondParam: number, thirdParam: any): any => { //my ...

Encountering the error message "Received 1 argument, when expecting 4" while attempting to utilize a vuex getter in TypeScript

I encountered an issue while unit testing a getter function. The error message Expected 4 arguments, but got 1. appeared when I attempted to use the getter. My application was built using Quasar and utilizes TypeScript. The value of HttpMocks.mockToken is ...