Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pagetransition before next page in Nextjs

Is there any way to archive a page transition that fits the following requirements:

  • I want to show a page transition when a page changes
  • The page transition should finish before the next page loads/shows
  • The page transition should run X seconds
  • The page transition is a component placed in _app.js

Currently, I do this in a gruesome way. In NuxtJS, it is possible to archive it via the Javascript Hooks. https://nuxtjs.org/docs/2.x/components-glossary/pages-transition

Thank you for the help :)

like image 932
J. Langer Avatar asked Jan 31 '21 10:01

J. Langer


1 Answers

You can hook into Next.js Router events, but you can not set how much time the transition should take.

E.g. if you want the transition to be 3 seconds:

  • if the Next.js transition takes 1 second, you can wait 2 seconds, but
  • if the Next.js transition takes 4 seconds, you can't do anything about it.

And you can not know for sure how long the Next.js transition will take.

custom "routing"

Anyway, if you rely on the Next.js transition never taking more time than your animation, you would have to "store" the old page view somehow, and show it instead of the new page as long as the animation runs.

From Next.js perspective the new page should be shown. I think this would not work with Next.js routing, you would have to do the "routing" (display of content depending on the url) yourself, I guess. E.g. design your App to always have something like two pages at once, one is shown, one is hidden and might be loading. Then you can switch between these two pages whenever you want.

You might want to have a look at the experimental feature React "Suspense" (I don't know, I haven't used it).

wait before routing

If you want to wait a while before the transition starts, you might do something like this:

const startAnimation = () => {
    return new Promise( ( resolve, reject ) => {
        console.log('...animate...');
        
        setTimeout( resolve, 3000 ); // <-- replace this line with your animation, and call resolve() when finished
    } );
};

const routerWrapper = {
    push: ( url ) => {
        startAnimation().then( () => {
            console.log('Next.js routing starts...');
            Router.push( url );
        })
    }
};

// ...

routerWrapper.push( newUrl ); // <-- this instead of Router.push( newUrl )

stop animation when routing completed

If you want to start an animation when Route.push() is called, and stop it when the Next.js transition is completed, you can use Next.js routerevents, e.g.:

export default function App( props: AppProps ) {
    const { Component, pageProps } = props;
    const router = useRouter()

    useEffect(() => {
        const routeChangeStart = (url, { shallow }) => {
            console.log('start animation');
        };

        const routeChangeComplete = (url, { shallow }) => {
            console.log('stop animation');
        };

        router.events.on('routeChangeStart', routeChangeStart);
        router.events.on('routeChangeComplete', routeChangeComplete);

        return () => {
            router.events.off('routeChangeStart', routeChangeStart);
            router.events.off('routeChangeComplete', routeChangeComplete);
        }
    }, [])

    // --
    return (
        <Component { ...pageProps } />
    );
}
like image 169
kca Avatar answered Nov 20 '22 18:11

kca