[Next.js]: Build page transitions with React Transition Group in Next.js
Next.js
05/11/2020
Overview
In this post I'll show how to apply page transitions (a.k.a. route transitions or page animations) in Next.js with React Transition Group. I'll be using Layout component to target specific component to apply the animation.
Here is GitHub repo

Install react-transition-group
npm i react-transition-groupLayout
Start by creating Layout component. Header is a tag that won't animate, but later transition will be applied to main container.
import React from "react"import "./styles.scss"
const Layout = ({ children }) => {  return (    <div className="layout">      {/* Header component that doesn't animate */}      <header>        <h1>Header</h1>      </header>      <main className="main">{children}</main>    </div>  )}
export default LayoutTransition
This transition will fade out to the left and fade in from the right with the changes in opacity and translateX() values.
This component needs location prop to be used as key property, so it can keep track of which component is coming in and out. location will be passed down from Layout component that will use useRoute function provided by Next.js
import {  TransitionGroup,  Transition as ReactTransition,} from "react-transition-group"const TIMEOUT = 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)`,  },  exiting: {    transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,    opacity: 0,    transform: `translateX(-50px)`,  },}
const Transition = ({ 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 TransitionLayout
With Transition component created, wrap the main container and pass down location with its pathname.
import React from "react"import { useRouter } from "next/router" import Transition from "../Transition" import "./styles.scss"
const Layout = ({ children }) => {  const router = useRouter()   return (    <div className="layout">      {/* Header component that doesn't animate */}      <header>        <h1>Header</h1>      </header>      <Transition location={router.pathname}>        <main className="main">{children}</main>      </Transition>    </div>  )}
export default LayoutLayout Styling
.layout {  display: flex;  flex-direction: column;  justify-content: center;  max-width: 680px;  margin: auto;  padding: 1rem;  background: #eaeaea;  overflow: hidden;
  .main {    padding: 1rem;    border-radius: 10px;    background: #ddd;  }}Pages
In order to navigate to different pages, create HomePage and AboutPage as an example
import React from "react"import Link from "next/link"
const HomePage = () => {  return (    <div>      <h1>HomePage</h1>      <Link href="about">        <a>Link To About</a>      </Link>    </div>  )}
export default HomePageimport React from "react"import Link from "next/link"
const AboutPage = () => {  return (    <div>      <h1>AboutPage</h1>      <Link href="/">        <a>Link To Home</a>      </Link>    </div>  )}
export default AboutPage_app.js
To apply Layout across different page, you need to wrap the Component (pages) inside _app.js
import Layout from "../components/Layout"
const App = ({ Component, pageProps, router }) => {  return (    <Layout>      <Component {...pageProps} key={router.route} />    </Layout>  )}export default AppThat's it!
After making changes to _app.js, be sure to restart the server for it to take effect
- [Next.js]: Set up Sass/Scss environment with Next.js
- [Next.js]: How to set up Express.js with Next.js