Next.js producing a duplicate output

While developing a web application using next js, I have encountered an issue with Router Push. It redirects to the login page successfully, but upon redirection to the login page, I am receiving double notifications. Can someone help me identify and fix this problem so that only one notification is shown?

(1) Dashboard Page

import { useRouter } from "next/router";
import { useContext } from "react";
import { toast } from "react-toastify";
import AppContext from "../../components/AppContext";
import DashLayout from "../../layouts/DashLayout";

function DashMain() {
    const router = useRouter();
    const server = useContext(AppContext);

    if (!server.auth) {
        router.push("/auth/login");
        toast.success("Please login to access the dashboard");
    }

    return (
        <>
            {server.auth ?
                <h2>Welcome to the Dashboard</h2>
                :
                <h1>Please login to access the dashboard</h1>
            }
        </>
    );

}

export default DashMain;

(2) Login Page

import { useContext, useState } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import Link from "next/link";
import Image from "next/image";
import AppContext from "../../components/AppContext";
import { toast } from "react-toastify";
import MainLayout from "../../layouts/MainLayout";

function Login() {

    const server = useContext(AppContext);
    const router = useRouter();

    if (server.auth) {
        router.push("/");
        toast.success("You are already logged in");
    }

    //states
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [errors, setErrors] = useState("");

    //Login Submit
    const submitForm = (e) => {
        e.preventDefault();
        server.login({ email, password, setErrors });
    }

    if (server.userLoading) {
        return (
            <div id="mainmodal">
                <div className="modalcontent">
                    <span className='loader'></span>
                </div>
            </div>
        );
    }

    return (
        <>
.......
        </>
    );
}

export default Login;

Login.getLayout = function getLayout(page) {
    return <MainLayout>{page}</MainLayout>;
};

Similarly, when the router redirects from the login page to the home page, I encounter the issue of receiving double notifications. I would appreciate a proper solution for this.

Answer №1

If you are utilizing React 18 in combination with StrictMode, be aware that a deliberate double-render occurs solely during development. This particular segment of the documentation sheds light on this aspect:

Explore more about React 18 and Strict Mode here.

This functionality is aimed at assisting with addressing adverse side effects, as illustrated by the following code snippet:

if (server.auth) {
  router.push("/");
  toast.success("You are already logged In");
}

When React 18 triggers its intentional double-render and your component undergoes two activations due to the preservation of context.auth upon unmounting and remounting of the login page.

An improved approach for handling this scenario would involve implementing a single hook to manage redirection logic based on detection of location.pathname. For example:

useRedirects.ts

import { useEffect } from 'react';
import { useLocation, useRouter } from 'react-router-dom';
import toast from 'toast';

const useRedirects = () => {
  const location = useLocation();
  const { pathname } = location;
  const router = useRouter();
  
  // perform actions when pathname changes
  useEffect(() => {
    // redirect to login page if not authenticated while accessing dashboard
    if (pathname === '/dashboard' && !server.auth) {
      router.push("/auth/login");
      toast.success("Please login to access dashboard");
    }
    // navigate to dashboard if authenticated while on login page
    if (pathname === '/login' && server.auth) {
      router.push("/");
      toast.success("You are already logged In");
    }
  }, [pathname]);
   
  return null;
};

Integrate this hook within your app.js file component:

import useRedirects from './useRedirects';

const App = () => {
  useRedirect();
  // ...
  // return ...
};

export default App;

Subsequently, the redundant code blocks on the dashboard and login pages can be eliminated, streamlining the process and enhancing clarity in React 18's debugging capabilities.

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

Using a JavaScript command, connect a function from one file to another file

I attempted to import a function because I want to click on <il> servies</il> and scroll to the services section on the home page. However, I simply want to click on the li element in the navbar and scroll to the service section on the home pag ...

The retrieval process takes place only one time or when I access the developer tools

I am currently developing a website where I need to retrieve reports from mongoDB and display markers on a map based on the locations of these reports. However, I am facing an issue where this functionality only works once when I initially open the website ...

When switching from page 1 to page 2 in a React MUI Data table, the cell data does not update to reflect the API response

Imagine a scenario where there is a parent component containing a child component that acts as a MUI data table. This child component receives API response data from the parent component as props. Problem: The data in the table loads perfectly on initial ...

Can static generation be achieved with Strapi, Next.JS, and docker-compose during the build process?

While attempting to compile my Next.JS application, which incorporates a getStaticProps() function to fetch data from Strapi, I encountered a failure in the fetch process. The culprit appears to be an inability to resolve the alias for the Strapi container ...

What is the best way to personalize Material UI elements, such as getting rid of the blue outline on the Select component?

Embarking on my journey of developing a React app, I made the decision to incorporate Material UI for its array of pre-built components. However, delving into the customization of these components and their styles has proven to be quite challenging for me ...

Guide to deploying a Next.js static export using Nginx: Troubleshooting deep link issues

After exporting my Next.js project to the out folder, I noticed a specific folder structure: out index.html terms.html privacy.html To serve these files using nginx, I configured it as follows: server { root /var/www/myproject/out; index index.h ...

What is the best way to customize the appearance of a toggle switch using useStyles in Material UI, rather than withStyles?

I need help with customizing the styling of an input form switch in Material UI. I want the track and button to turn red when the switch is on, similar to this example. I have tried using the withStyles method following examples on the Material UI website, ...

ESLint is cautioning developers that React Query mutations should be be added to the dependency array

When using the react-query library, I encountered a warning about the ESLint useEffect dependency. Here is an example of my code: const postProductMutation = useMutation(...); useEffect(() => { postProductMutation.mutateAsync() }, []) The issue is ...

What is the correct way to import React's experimental hooks?

I am eager to explore the cutting-edge and unreleased features of React, particularly the "useEffectEvent" hook. However, I have encountered a problem while trying to import this specific feature from the React package. Whenever I attempt to import somet ...

Issue with Dismissing Material UI Snackbar

Having trouble dismissing the snackbar by clicking away or on the "X" button. It's supposed to disappear after 10 seconds but it just stays there! Not sure what I'm doing wrong. const Footer = () => { const [snackbarState, setSnackbarState] = ...

Attempting to invoke setState on a Component before it has been mounted is not valid - tsx

I've searched through various threads regarding this issue, but none of them provided a solution that worked for me. Encountering the error: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a b ...

Why isn't the hover function working on the table row element?

When I try to apply a hover effect on tbody and td elements, it works perfectly. However, when I apply the same effect to the tr element, it doesn't work as expected. I am using inline style (js pattern) rather than CSS code and incorporating Radium i ...

What is the best way to handle a rejected promise in Redux when using createAsyncThunk with Next.js?

I'm attempting to set up a player using a POST request but I keep encountering the error of promise rejected in redux devtool. Interestingly, the data is visible on the UI. The tools being utilized are createAsyncThunk and createEntityAdapter: creat ...

Error 400 occurs when using mutation, yet the same mutation successfully executes in GraphiQL

After following tutorials and attempting to learn GraphQL with React and Express, I've hit a roadblock. The mutation works fine when I test it in graphiql but fails when called from my client. Client Code: async addBook(params) { var title = par ...

Struggling to display nested data using ReactJS and Material-UI?

Struggling to implement Tabs and display data from a JSON file in Reactjs with an older version of material-ui. Despite following suggestions on StackOverflow to correct the nested map in JSX, the data is still not appearing under each tab. For reference ...

What could be causing my Material UI Divider to appear invisible within a Material UI Container or Paper component?

Hey there! I am absolutely smitten with Material UI - it's incredibly versatile. However, I'm facing a bit of trouble with the Material UI Divider not displaying when nested within either a Container or Paper component. I've looked into it ...

Using React Native to create a concise text component that fits perfectly within a flexbox with a

Within a row, there are two views with flex: 1 containing text. <View style={{ flexDirection: "row", padding: 5 }}> <View style={{ flex: 1 }}> <Text>Just a reallyyyyyyyy longgggg text</Text> </View> ...

The required and defaultValue attributes seem to be malfunctioning on my Textfield, although the placeholder feature is functioning properly

In the card below, I have implemented a simple edit functionality. Upon clicking edit, a textfield is supposed to appear for me to make changes and save them. However, I am facing issues with the required and defaultValue attributes in my Textfield, alth ...

What is the process for rendering a React class component using React HashRouter and Apollo client?

I've run into an issue with my project that involves using only React class components and fetching data from an Apollo server. The problem I'm facing is that, in Chrome, only the Navbar.jsx component is rendering. Even when I navigate to one o ...

Creating a standard arrow function in React using TypeScript: A Step-by-Step Guide

I am currently working on developing a versatile wrapper component for Apollo GraphQL results. The main objective of this wrapper is to wait for the successful completion of the query and then render a component that has been passed as a prop. The componen ...