DEV Community

Cover image for How to add page transitions to a nextjs app
Navicstein Rotciv
Navicstein Rotciv

Posted on

How to add page transitions to a nextjs app

This tutorial assumes that you're already familiar with next.js and just what to add transitions to your pages and that you're have hope of using typescript

Step 1

Install required dependency

$ npm install react-transition-group
Enter fullscreen mode Exit fullscreen mode

if you're using Typescript install the types for it

$ npm install -D @types/react-transition-group
Enter fullscreen mode Exit fullscreen mode

Step 2

create a Transition.tsx component in the component folder

import {
  TransitionGroup,
  Transition as ReactTransition,
} from "react-transition-group"

import { ReactChild } from "react"

type TransitionKind<RC> = {
  children: RC
  location: string
}

const TIMEOUT: number = 200

const getTransitionStyles = {
  entering: {
    position: `absolute`,
    opacity: 0,
    transform: `translateX(50px)`,
  },
  entered: {
    transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
    opacity: 1,
    transform: `translateX(0px)`,
    animation: "blink .3s linear 2",
  },
  exiting: {
    transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
    opacity: 0,
    transform: `translateX(-50px)`,
  },
}

const Transition: React.FC<TransitionKind<ReactChild>> = ({
  children,
  location,
}) => {
  return (
    <TransitionGroup style={{ position: "relative" }}>
      <ReactTransition
        key={location}
        timeout={{
          enter: TIMEOUT,
          exit: TIMEOUT,
        }}
      >
        {(status) => (
          <div
            style={{
              ...getTransitionStyles[status],
            }}
          >
            {children}
          </div>
        )}
      </ReactTransition>
    </TransitionGroup>
  )
}
export default Transition
Enter fullscreen mode Exit fullscreen mode

Step 3

Next, import this Transition.tsx component to your layouts/MainLayout or _app.tsx if you're doing this in the _app.tsx be sure to replace children with <Component {...pageProps} />.

We have imported useRouter from next//router and passed the pathname to location props

// import this `Transition.tsx` component to your `layouts/MainLayout` or `_app.tsx`
import React, { Fragment } from "react"
import Transition from "../components/Transition"
import { useRouter } from "next/router"

const MainLaylout: React.FC = () => {
  const router = useRouter()

  return (
    // you may import your header and footer here too
    <Fragment>
      <Transition location={router.pathname}>
        <div className="min-h-screen">{children}</div>
      </Transition>
    </Fragment>
  )
}
// React.memo may not be important
export default React.memo(MainLaylout)
Enter fullscreen mode Exit fullscreen mode

Step 4

Now you have everything ready it's time to use the MainLayout in our pages..
to use the layout, import and wrap your pages with MainLayout

for example

import React, { Fragment } from "react"
// path to your main layout
import MainLayout from "layouts/MainLayout"

const IndexPage: React.FC = (props) => {
  return (
    <MainLayout>
      <div> replace with your content here..</div>
    </MainLayout>
  )
}
export default React.memo(IndexPage)
Enter fullscreen mode Exit fullscreen mode

Wrap each of your pages with the main layout, congratulations, you've just added page transitions to a nextjs app

Top comments (4)

Collapse
 
larsejaas profile image
Lars Ejaas

This is really cool. I need to dig a bit into this, as I do not get any page-transitions between pages when transitioning between pages build on the same page-file but on different routes. But this is a really solid starting point and a lot lighter on bundle size compared to something like Framer. Thanks for the article - it really helped a lot!

Collapse
 
larsejaas profile image
Lars Ejaas

Small follow up if anyone is facing a similar issue:

router.pathname is the path to the page-file. So when you pass routher.pathname as a prop to the Transition component you will only get a transition when you navigate to a page that is based on another page-file. This will probably work fine in most instances, but if you use a CMS for content (my current project uses headless WordPress) you could be using the same file ( e.g. page/[...page].tsx ) to generate a lot of different pages.
The workaround is to pass router.asPath instead. This way you will get a transition every time the page is navigated to a different url.

Collapse
 
hocoh profile image
Hocoh • Edited

Awesome bro, you saved my day !
it works fine now,
looking forward for your next tutorials.

Collapse
 
arionarian profile image
Rian Ariona

Not working if the page has serverSideProps 🤷‍♂️ Any idea to make this work?