如何检测 Next.js 中 URL 哈希的变化?

App*_*ran 16 url reactjs next.js url-fragment

我们如何检测 Next.js 项目的 URL 哈希变化?

我不想每次 slug 更改时都重新加载页面。

我无法使用,<Link>因为我的所有数据都来自数据库

示例:
http://example/test#url1
当单击从 到 的 标签时
http://example.com/test#url2

尝试了下面的方法,但这似乎仅适用于路径更改。

import React, { useEffect,useState } from 'react';
import { useRouter } from 'next/router'

const test = () => {
    const router = useRouter();

    useEffect(() => {
        console.log(router.asPath);
    }, [router.asPath]);

    return (<></>);
};

export default test;
Run Code Online (Sandbox Code Playgroud)

jul*_*ves 23

hashChangeStart您可以使用来自的事件监听哈希更改router.events

const Test = () => {
    const router = useRouter();

    useEffect(() => {
        const onHashChangeStart = (url) => {
            console.log(`Path changing to ${url}`);
        };

        router.events.on("hashChangeStart", onHashChangeStart);

        return () => {
            router.events.off("hashChangeStart", onHashChangeStart);
        };
    }, [router.events]);

    return (
        <>
            <Link href="/#some-hash">
                <a>Link to #some-hash</a>
            </Link>
            <Link href="/#some-other-hash">
                <a>Link to #some-other-hash</a>
            </Link>
        </>
    );
};
Run Code Online (Sandbox Code Playgroud)

如果您不使用next/linknext/router进行客户端导航(不建议在 Next.js 应用程序中使用),那么您需要监听windowhashchange事件

你的useEffect看起来像下面这样。

useEffect(() => {
    const onHashChanged = () => {
        console.log('Hash changed');
    };

    window.addEventListener("hashchange", onHashChanged);

    return () => {
        window.removeEventListener("hashchange", onHashChanged);
    };
}, []);
Run Code Online (Sandbox Code Playgroud)


pio*_*son 10

如果您依赖 URL 哈希进行多次重新渲染或状态更改,请注意 NextJShashChangeStart事件不考虑浏览器刷新或直接浏览器 URL 地址导航

完整的解决方案可能需要事件侦听器的组合来覆盖所有边缘情况。

const useUrlHash = (initialValue) => {
  const router = useRouter()
  const [hash, setHash] = useState(initialValue)

  const updateHash = (str) => {
    if (!str) return
    setHash(str.split('#')[1])
  }

  useEffect(() => {
    const onWindowHashChange = () => updateHash(window.location.hash)
    const onNextJSHashChange = (url) => updateHash(url)

    router.events.on('hashChangeStart', onNextJSHashChange)
    window.addEventListener('hashchange', onWindowHashChange)
    window.addEventListener('load', onWindowHashChange)
    return () => {
      router.events.off('hashChangeStart', onNextJSHashChange)
      window.removeEventListener('load', onWindowHashChange)
      window.removeEventListener('hashchange', onWindowHashChange)
    }
  }, [router.asPath, router.events])

  return hash
}
Run Code Online (Sandbox Code Playgroud)