An Interest In:
Web News this Week
- April 26, 2024
- April 25, 2024
- April 24, 2024
- April 23, 2024
- April 22, 2024
- April 21, 2024
- April 20, 2024
Page Transition Effect in NextJS
Before we start building any component for the transition, let's briefly talk about how NextJS renders pages.
First, let's take a look at _app.js
:
export default function MyApp({ Component, pageProps }) { return ( <Component {...pageProps} /> );}
The "_app.js" is the entry point for NextJS to start render page. When you navigation to a different page, the page component pass to MyApp as Component
.
Therefore, in order to make a transition effect, we need to prevent
NextJS from rendering the new page before transition effect is done.
Now, let's create the layout component with some navigation links:
export default function TransitionLayout({ children }) { return ( <div> <nav> <Link href="/">Home</Link> <Link href="/about">About</Link> </nav> <div> {children} </div> </div> );}
And add to _app.js
function MyApp({ Component, pageProps }) { return ( <TransitionLayout> <Component {...pageProps} /> </TransitionLayout> );}
Now, let's start working on the TransitionLayout
First, we need to prevent the rendering the new page
We can add a state to hold the current children, and only render the displayChildren
.
We use children
as the default value for displayChildren
.
export default function TransitionLayout({ children }) { const [displayChildren, setDisplayChildren] = useState(children); return ( <div> ... <div> {displayChildren} </div> </div> );}
Now, if you click the link, the content of the page will not change.
Next, we add css and transition stage
.content { opacity: 0; background-color: cornflowerblue; transition: 1s;}.fadeIn { opacity: 1;}
export default function TransitionLayout({ children }) { const [displayChildren, setDisplayChildren] = useState(children); const [transitionStage, setTransitionStage] = useState("fadeOut"); ... return ( <div> ... <div className={`${styles.content} ${styles[transitionStage]}`} > {displayChildren} </div> </div> );}
Now, the component will by default at 'fadeOut' stage, and we want to let it enter the 'fadeIn' stage at first time render, so let's add:
useEffect(() => { setTransitionStage("fadeIn"); }, []);
Next, we want the component to enter 'fadeOut' when new children is received.
useEffect(() => { if (children !== displayChildren) setTransitionStage("fadeOut"); }, [children, setDisplayChildren, displayChildren]);
And, render new children when 'fadeOut'is done, then re-enter 'fadeIn' stage.
... return( ... <div onTransitionEnd={() => { if (transitionStage === "fadeOut") { console.log("fading out"); setDisplayChildren(children); setTransitionStage("fadeIn"); } }} className={`${styles.content} ${styles[transitionStage]}`} > {displayChildren} </div> )
And, here is the demo and the completed code for the layout component:
Node: The demo will take sometime for CodeSandbox to start.
import Link from "next/link";import { useState, memo, useEffect } from "react";import styles from "./Layout.module.css";export default function TransitionLayout({ children }) { const [displayChildren, setDisplayChildren] = useState(children); const [transitionStage, setTransitionStage] = useState("fadeOut"); useEffect(() => { setTransitionStage("fadeIn"); }, []); useEffect(() => { if (children !== displayChildren) setTransitionStage("fadeOut"); }, [children, setDisplayChildren, displayChildren]); return ( <div> <nav> <Link href="/">Home</Link> <Link href="/about">About</Link> </nav> <div onTransitionEnd={() => { if (transitionStage === "fadeOut") { console.log("fading out"); setDisplayChildren(children); setTransitionStage("fadeIn"); } }} className={`${styles.content} ${styles[transitionStage]}`} > {displayChildren} </div> </div> );}
Thank you all!!
Original Link: https://dev.to/anxinyang/page-transition-effect-in-nextjs-9ch
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To