在发生nextjs 13应用程序路由器之前检测导航事件,然后防止它发生

问题描述 投票:0回答:4

使用 nextjs 12(页面路由器),从“next/router”返回的路由器具有您可以侦听和适当处理的导航事件。 这里是文档。

一个具体事件是

routeChangeStart
。当您希望在用户离开页面之前提示他们时,您已侦听该事件,然后打开模式并抛出错误以阻止导航。

使用 nextjs 13(应用程序路由器),从“next/navigation”返回的路由器不具有订阅事件的相同能力。

文档中有一个解决方案可以告知路线何时已更改。它使用了两个新的钩子

  • usePathname
  • useSearchParams

就是解决方案。

我想知道之前路线即将改变。

您如何知道 nextjs 13 应用程序(使用应用程序路由器)何时将要导航,以及如何阻止它这样做?

events navigation router next.js13 onbeforeunload
4个回答
0
投票

如果您使用 Link 组件进行导航,则可以使用自定义组件切换它并使用 useRouter 钩子。


0
投票

为了在发生之前检测导航事件,我在

NavigationEvents
中使用钩子 usePathname + useRef + useEffect (来自 Nextjs13 的链接)

我的下面的代码正在检查用户是否导航关闭

/about

export function NavigationEvents() {

    // Get the current pathname from the router
    const pathname = usePathname()
    
    // Create a ref to store the previous pathname
    const ref = useRef(pathname)
    
    useEffect(() => {
    // Check if the pathname has changed and if the previous pathname was '/page'
    if (ref.current !== pathname &&
        ref.current === '/about') { 
        // Do something before the page changes
        // For example, you could show a confirmation dialog or save some data
    }
    
    // Update the ref to store the current pathname
    ref.current = pathname
    }, [pathname])
    
    // Return null because this component doesn't render any UI elements
    return null
}

注意:必须将

NavigationEvents
添加到根布局才能正常工作(不是子页面布局)

reference photo


0
投票

感谢 Steven Linn (github)

注意:这只是问题第一部分的解决方案。那就是“你怎么知道 nextjs 13 应用程序(使用应用程序路由器)何时将要导航?” 我不相信这个解决方案可以用来防止导航离开。此外,它不适用于后退和前进按钮。但半解决方案总比没有解决方案好,所以我来了。

我遇到了这个问题,但在下一个 14.1.0 中。我能够在路由更改发生之前监听路由更改的方法是引用 this github 评论。他们建议使用他们的 nextjs13-router-events 包

但是看到我在下一个 14.1.0 中需要这个,我采取了自己的(类似)步骤。总结一下:

  • RouteChangeProvider
    Link
    useRouteChange
    复制粘贴组件代码。

  • 将所有

    import Link from "next/link";
    更改为
    import Link from "path/to/custom/Link";

  • RouteChangeProvider

    包装您的应用程序
import { RouteChangeProvider } from './RouteChangeProvider';
...
return (
  <RouteChangeProvider>
    {children}
  </RouteChangeProvider>
)
  • 在需要监听路由变化的组件中使用钩子:
import useRouteChange from './useRouteChange';
...
export default function Component(props: any) {
  ...
  useRouteChange({
    onRouteChangeStart: () => {
      console.log('Put code here to run BEFORE route changes');
    },
    onRouteChangeComplete: () => {
      console.log('onComplete 3');
    }
  });
  ...
}
  • (下一个 14.1.0 的附加步骤)
    Link.tsx
    组件中,将
    const { onRouteChangeStart } = useRouteChangeContext();
    线移至
    if (!useLink) return <a href={href} onClick={onClick} {...rest} />;
  • 上方
  if (!useLink) return <a href={href} onClick={onClick} {...rest} />;

  const { onRouteChangeStart } = useRouteChangeContext();

成为

  const { onRouteChangeStart } = useRouteChangeContext();

  if (!useLink) return <a href={href} onClick={onClick} {...rest} />;

  • (下一个 14.1.0 的附加步骤)
    RouteChangeProvider.tsx
    中,将
    onRouteChangeComplete
    添加到使用它的 useEffect 的依赖项中。
useEffect(() => onRouteChangeComplete(), [pathname, searchParams]);

成为

useEffect(() => onRouteChangeComplete(),[pathname, searchParams, onRouteChangeComplete]);

附注最后两个步骤是针对我在创建生产版本时收到的错误和警告的修补程序。


-1
投票
"use client";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect, useRef } from "react";
import "../../css/loader.css";

export default function Loader() {
  const path = usePathname();
  const params = useSearchParams();
  const loaderRef = useRef(null);

  if (loaderRef?.current) {
    loaderRef.current.classList.remove("loading-bar-end");
    loaderRef.current.classList.add("loading-bar-start");
  }
  useEffect(() => {
    if (loaderRef?.current) {
      loaderRef.current.classList.remove("loading-bar-start");
      loaderRef.current.classList.add("loading-bar-end");
    }
  });

  return (
    <div className="fixed z-[50] top-0 w-full">
      <div
        ref={loaderRef}
        className="z-[50] bg-danger pb-1 rounded-full loading-bar-start"
      ></div>
    </div>
  );
}

其实很简单!我认为他们的文档使其成为 有点令人困惑,但是当您使用 Link 时会发生什么 或 useRouter 进行导航,usePathname 捕获的路径 路线没有实际加载路线,所以你可以像 在这里开始加载,然后在 useEffect 中你可以停止 加载(使用 CSS 动画或任何你喜欢的东西)。依赖关系 useEffect 可以是 [path, params (useSearchParams*)] 或 没什么,完全取决于你!类似地,useSearchParams 也是如此!

© www.soinside.com 2019 - 2024. All rights reserved.