URL's hash changing in Next.js 13
Asked Answered
T

0

6

Is it possible to spy for the #hash in Next.js 13v apps?

What do I do wrong? Its seems like 'hashchange' event just doesn't work an anaught - only for the first app render.

Now I'm trying to do this, but it's doesn't work:

My layout.tsx:

import './globals.css'
import './page.css'
import type { Metadata } from 'next'
import { TheMenu } from '@/components/TheMenu'

export const metadata: Metadata = {
    title: 'Test app',
    description: 'Generated by create next app'
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html>
            <body>
                {children}
                <TheMenu />
            </body>
        </html>
    )
}

My TheMenu.tsx component - which actually changes the #hash:

'use client'

import './menu.css'
import Link from 'next/link'
import route from '@/config/routing'
import { useState } from 'react'

const TheMenu = () => {
    const [open, setOpen] = useState(false)

    const toggleMenu = () => {
        setOpen(!open)
    }

    return (
        <div className="menu__wrapper">
            <button className={`menu__btn`} type="button" onClick={toggleMenu}>
                Open/Close
            </button>
            {open && (
                <ul className="menu__list">
                    {Object.entries(route.modules).map(([key, item]) => (
                        <li key={key}>
                            <Link className={`menu__link`} href={item.href} onClick={toggleMenu}>
                                {item.name}
                            </Link>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    )
}

export { TheMenu }

And finally page.tsx, where I need to render different components in dependency of current #hash:

'use client'

import route from '@/config/routing'
import { Component1 } from '@/components/other_components/Component1 '
import { Component2 } from '@/components/other_components/Component2 '
import { Barlow } from 'next/font/google'
import { useEffect, useState } from 'react'

const barlow = Barlow({ subsets: ['latin'], weight: '900' })

export default function Home() {
    const [component, setComponent] = useState(<Component1 />)

    const componentSwitcher = () => {
        console.log(window.location.hash)
        switch (window.location.hash) {
            case '#component1':
                setComponent(<Component1 />)
                break
            case '#component2':
                setComponent(<Component2 />)
                break
            default:
                setComponent(<Component1 />)
                break
        }
    }

    useEffect(() => {
        window.addEventListener('hashchange', componentSwitcher)

        componentSwitcher()

        return () => {
            window.removeEventListener('hashchange', componentSwitcher)
        }
    }, [])

    return (
        <>
            <div className="container">
                <div className="main__wrapper">
                    <p className={`${barlow.className} welcome__text`}>
                        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Soluta placeat necessitatibus animi quam, ipsum minima possimus enim cumque nesciunt distinctio.
                    </p>
                </div>
            </div>
            {component}
        </>
    )
}
Tetravalent answered 4/8, 2023 at 23:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.