Reputation: 63
I'm trying to apply page transition effect in Next.js. Because of the project limitation, I cannot use external library except from GSAP. I've achieved similar effect using useMemo
to track the children, and update the display children when the outro page transition completes. Then initiate the reveal the page after the display children updates.
But the only thing is when the page unmount (during outro-animation), some components are being re-run. The page got re-run only in build mode (not in dev mode). Any ideas/ direction on why this is happening? Or other method on applying the page transition is helpful. Thank you.
Here's the code: _app.tsx
function MainApp({ Component, pageProps }: AppProps) {
return (
<CustomPageTransition>
<Component {...pageProps} key={router.asPath} />
</CustomPageTransition>
)
}
CustomPageTransition.tsx
export const CustomPageTransition = function ({ children }: { children: ReactNode}) {
const [displayChildren, setDisplayChildren] = useState(children)
const memoizedChildren = useMemo(() => children, [children])
const [readyToRenderNextPage, setReadyToRenderNextPage] = useState(false)
// startCover gsap animation
const startCover = useCallback(() => {
const coverTl = gsap.timeline()
if (el.current) {
coverTl.to(el.current, {
opacity: 1,
ease: 'Power2.inOut',
duration: 0.3,
onComplete: () => {
setTimeout(() => {
setReadyToRenderNextPage(true)
}, 300)
},
})
}
}, [el])
// outro page transition after first load
useEffect(() => {
// on exit page
router.events.on('routeChangeStart', startCover)
return () => {
router.events.off('routeChangeStart', startCover)
}
}, [router.events, startCover])
// intro page transition after first load
useEffect(() => {
if (isIntroPageTransitionAnimating) { // true when page component mounted, this is updated via Context
startReveal()
}
}, [isIntroPageTransitionAnimating, startReveal])
useIsomorphicLayoutEffect(() => {
// outro: switch to new children when readyToRenderNextPage
if (memoizedChildren !== displayChildren && readyToRenderNextPage) {
setDisplayChildren(children)
}
}, [memoizedChildren, displayChildren, readyToRenderNextPage])
return (
<>
<StyledPageTransition ref={el} className={pageTransitionClass} />
{displayChildren}
</>
}
Upvotes: 2
Views: 576