`Is there a way to avoid extra re-renders caused by parameters in NextJS?`

I am currently in the process of implementing a standard loading strategy for NextJS applications using framer-motion.

function MyApp({ Component, pageProps, router }) {
    const [isFirstMount, setIsFirstMount] = useState(true);

    useEffect(() => {
        const handleRouteChange = () => {
            setIsFirstMount(false);
        };

        router.events.on("routeChangeStart", handleRouteChange);

        // If the component is unmounted, unsubscribe
        // from the event with the `off` method:
        return () => {
            router.events.off("routeChangeStart", handleRouteChange);
        };
    }, [router]);
    console.log("My App ran");
    return (
        <Layout>
            <AnimatePresence exitBeforeEnter>
                <motion.div exit={{ opacity: 0 }}>
                    {isFirstMount && <InitialTransition />}
                    <motion.div
                        initial="initial"
                        animate="animate"
                        variants={content(isFirstMount)}
                        className="space-y-12"
                    >
                        <Component
                            isFirstMount={isFirstMount}
                            key={router.route}
                            {...pageProps}
                        />
                    </motion.div>
                </motion.div>
            </AnimatePresence>
        </Layout>
    );
}

I encountered an issue related to parameters. When utilizing parameters during the initial load (such as refreshing the browser), NextJS triggers an additional render. This behavior seems to be caused by NextJS updating the router query object. For instance,

WEBSITE.com/ // works - you will see the black loading screen, the black loading screens slides down, and the child objects start popping on
// vs
WEBSITE.com/?test=test // fails - you will see the black loading screen flash in and out of view before the rest of the app proceeds

I have created a codesandbox example. On the client side, test by adding or removing ?test=test at the end of the URL.

Is there a way to prevent the extra re-render or ensure that the loader functions consistently regardless of the presence of parameters?


Update

I tested @Mokhtar's code. Surprisingly, it did not make any changes but the transitions started working smoothly. After some investigation, I discovered that eliminating all the logic related to isFirstMount and useEffect resulted in correct transitioning.

function MyApp({ Component, pageProps, router }) {
    console.log("My App ran");
    return (
        <Layout>
            <AnimatePresence exitBeforeEnter>
                <motion.div exit={{ opacity: 0 }}>
                    <InitialTransition />
                    <motion.div
                        initial="initial"
                        animate="animate"
                        variants={content(true)}
                    >
                        <Component key={router.route} {...pageProps} />
                    </motion.div>
                </motion.div>
            </AnimatePresence>
        </Layout>
    );
}

Can anyone explain why this approach is successful? Initially, I believed that the exit opacity/sliding action would only occur when the Component was removed.

Answer №1

Your <InitialTransition /> element is being unmounted due to a shallow change in your route (check out https://nextjs.org/docs/routing/shallow-routing) which triggers the execution of your handleRouteChange function.

To resolve this issue, consider the following implementation for handleRouteChange:

const handleRouteChange = (url, { shallow }) => {
  if (shallow && !isFirstMount) {
    setIsFirstMount(false);
  }
};

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

During the rendering process, the property "instance" was attempted to be accessed but is not defined

I am having trouble creating a Contact Us page using v-model. My code keeps throwing these errors: Property "inputted_name" was accessed during render but is not defined on instance Property "inputted_email" was accessed during render but is not defined o ...

"Exploring the capabilities of Rxjs ReplaySubject and its usage with the

Is it possible to utilize the pairwise() method with a ReplaySubject instead of a BehaviorSubject when working with the first emitted value? Typically, with a BehaviorSubject, I can set the initial value in the constructor allowing pairwise() to function ...

The length of Array(n) is incorrect when running on production in Next.js

My goal is to create an array of a specific length in TypeScript, but I am encountering an issue where the array length is incorrect when running my app in production mode (minified version). For example, when I execute console.log(Array(3)); in developme ...

Notify user when Redux action is completes in ReactJS/Redux application

I've been working on a custom notification component that should display a message and then hide itself after a few seconds when certain redux actions, like login_fail, are triggered. However, I'm facing an issue where the message briefly pops up ...

An issue with the "req" parameter in Middleware.ts: - No compatible overload found for this call

Currently, I am utilizing the following dependencies: "next": "14.1.0", "next-auth": "^5.0.0-beta.11", "next-themes": "^0.2.1", In my project directory's root, there exists a file named midd ...

Is your Cloud Functions task generating an Array when querying?

To access items and products in my database, I need to retrieve the "ean" field from the product and check if it matches the one in the request body. The structure of my database is as follows: "cart": { "items": { "0": {info here}, "1": {info ...

Is there a way to activate ng-class on only a single element?

In my code, I am using ng-repeat and ng-class for each element to select elements and add borders for the selected ones. <div class="main-block_channel_create"> <section class="parent_messageList cancelDelete"> <div id="section_animate" ...

Retrieve all data points if both latitude and longitude are present in the XML dataset

XML data to retrieve details <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <results> <result> <Country_Code>IN</Country_Code> <Country_Name>India</Country_Name> <Region_Nam ...

What is the correct way to utilize refetchOnReconnect for a builder.mutation endpoint in @redux/toolkit/query?

I'm having an issue with the Redux refetchOnReconnect option not working even after I have called the setupListener(store.dispatch) in my redux store.tsx file and set refetchOnReconnect=true to the endpoint hook call. store.tsx file 'use client& ...

utilizing vue model attributes with `${}`

I am encountering an issue with my code. Initially, :src="labels[index]" was working fine for me. However, as my codebase expanded, I needed to use ${app.labels[index]}. Simply using ${app.labels} works, but the addition of [index] causes it to b ...

Nextjs exposes a bug in react-bootstrap's navbar component

After integrating react-bootstrap with nextjs, I encountered a strange issue with the NavBar component. The problem arises when I first load the navbar - everything appears as expected, https://i.stack.imgur.com/R9guE.png but upon refreshing the page, CS ...

What is preventing me from accessing a JSON file on Vercel while utilizing Next.js SSR?

I am currently working on a basic Next.js project with three main files. My goal is to populate the index page with data from a JSON file. Interestingly, when I deploy the project to Vercel using getStaticProps, everything functions correctly. However, up ...

Data from Rails 6 is not appearing on Heroku's local environment or within the application

I recently attempted to deploy a Rails backend and React frontend application on Heroku. While the frontend functions properly, I am facing issues with data not displaying on the Heroku site and when using heroku local. Strangely enough, everything works p ...

Determining whether a page was loaded due to a back button press in NextJS

Is there a way to determine if a route or page was loaded due to the user pressing the back button on the browser in NextJS, so that I can load specific data accordingly? ...

Using Vue and Vuex to wait for asynchronous dispatch in the created hook

I'm struggling to implement asynchronous functionality for a function that retrieves data from Firebase: Upon component creation, I currently have the following: created(){ this.$store.dispatch("fetchSections"); } The Vuex action looks ...

Unlocking elements in Vue.js through functions

Looking to dynamically add a class to the label element when focusing on an input element below it. The current HTML and JS code I'm using is as follows: HTML: <label for="formProductId" ref="productIdLabel" class="form-element-title">Product ...

Rendering sibling components on Multiple Select Material UI in React

Here is my current challenge: I am trying to implement a multiple select feature with checkboxes in React using Material UI. The desired outcome should resemble the image linked below: https://i.stack.imgur.com/TJl8L.png I have structured my data in an a ...

I am struggling to grasp the flow of this code execution

Hi there, I just started my journey in JavaScript learning about two weeks ago. I would really appreciate it if someone could walk me through the execution steps of the code provided below. function sort(nums) { function minIndex(left, right) { ...

MUI: Autocomplete received an invalid value. None of the options correspond to the value of `0`

Currently, I am utilizing the MUI autocomplete feature in conjunction with react-hook-form. I have meticulously followed the guidance provided in this insightful response. ControlledAutoComplete.jsx import { Autocomplete, TextField } from "@mui/mater ...

Removing leading zeros from numeric strings in JSON data

I am facing an issue with my jQuery-based JavaScript code that is making an Ajax call to a PHP function. updatemarkers.xhr = $.post( ih.url("/AjaxSearch/map_markers/"), params).done( function(json) { <stuff> } The PHP function returns the follo ...