How to dynamically change the value of the text based on the document.title

29 Views Asked by At

I have a project with next.js page router

enter image description here

I'm making a page transition with framer-motion and I want the paragraph to have the value of the current document.title

It works fine the issue is let's say if I'm on the about page and the title is about when I move to contact the paragraph animation will show about then contact, and if I went from contact to home I will see contact then home

import React, { useEffect, useState } from 'react';
import { motion } from 'framer-motion';
import { useRouter } from 'next/router';
import { text, curve, translate } from './animation';

const anim = (variants: { [key: string]: any }) => {
    return {
        variants,
        initial: "initial",
        animate: "enter",
        exit: "exit"
    }
}

export default function Curve({ children, backgroundColor }: { children: React.ReactNode, backgroundColor: string }) {
    const router = useRouter();
    const [dimensions, setDimensions] = useState<{ width: number | null, height: number | null }>({ width: null, height: null });
    const [pageTitle, setPageTitle] = useState<string | null>(null);

    useEffect(() => {
        function resize() {
            setDimensions({
                width: window.innerWidth,
                height: window.innerHeight
            })
        }
        resize();
        window.addEventListener("resize", resize)
        return () => {
            window.removeEventListener("resize", resize);
        }
    }, [])

    useEffect(() => {
        setPageTitle(document.title || null);
        const handleRouteChange = (url: string) => {
            setPageTitle(document.title || null);
        };
        router.events.on('routeChangeComplete', handleRouteChange);
        return () => {
            router.events.off('routeChangeComplete', handleRouteChange);
        };
    }, [router.events]);

    return (
        <div className='page curve' style={{ backgroundColor }}>
            <div style={{ opacity: dimensions.width == null ? 1 : 0 }} className='background' />
            <motion.p className='route' {...anim(text)}>
                {pageTitle}
            </motion.p>
            {dimensions.width != null && <SVG {...dimensions} />}
            {children}
        </div>
    )
}

const SVG = ({ height, width }: { height: number | null, width: number | null }) => {

    if (width == null || height == null) {
        return null;
    }

    const initialPath = `
        M0 300 
        Q${width / 2} 0 ${width} 300
        L${width} ${height + 300}
        Q${width / 2} ${height + 600} 0 ${height + 300}
        L0 0
    `

    const targetPath = `
        M0 300
        Q${width / 2} 0 ${width} 300
        L${width} ${height}
        Q${width / 2} ${height} 0 ${height}
        L0 0
    `

    return (
        <motion.svg {...anim(translate)}>
            <motion.path {...anim(curve(initialPath, targetPath))} />
        </motion.svg>
    )
}
0

There are 0 best solutions below