How to prevent additional re-renders due to params on NextJS?

I’m setting up a generic loading strategy for NextJS apps 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 ran into an issue with params. When using params during initial loading (such as clicking on the refresh button on browser), NextJS loads an additional time. I believe its due to NextJS’s router query object update. For example,

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 made a codesandbox sample. On the browser side, test by adding or removing ?test=test to the end of the url.

How can I prevent the additional re-render or get the loader to work the same way regardless of having a param or not?

22 thoughts on “How to prevent additional re-renders due to params on NextJS?”

  1. Your <InitialTransition /> component is getting unmounted because of your route being called with a shallow change (https://nextjs.org/docs/routing/shallow-routing) and therefore calling your handleRouteChange handler.

    The following handleRouteChange implementation should fix it.

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

Leave a Comment