【问题标题】:listen for router change via useEffect in NextJS通过 NextJS 中的 useEffect 监听路由器变化
【发布时间】:2021-07-07 19:43:08
【问题描述】:

当用户通过导航更改页面时,我试图获得一个 useEffect 来执行一些代码。

我的问题是 useEffect 不会在路由更改时执行(不会显示在控制台中)。它只会在第一个初始页面加载时显示,之后不会显示

我使用了来自 nextJS 的 google analytics 示例

这是我的简单 _app.tsx

import type { AppProps } from "next/app";
import "./styles/css.scss";
import { useRouter } from "next/dist/client/router";
import { useEffect} from "react";



const Child: React.FC = ({ children }) => {
  return (
    <>
      <div>{children}</div>
    </>
  );
};

const App = ({ Component, pageProps }: AppProps) => {
  const router = useRouter();

  useEffect(() => {

    console.log("called");

  }, [router.events]);
  return (
    <>
      <Child>
        <Component {...pageProps} />
      </Child>
    </>
  );
};
export default App;

【问题讨论】:

    标签: reactjs next.js


    【解决方案1】:

    您可以为此使用useLocation

    const App = ({ Component, pageProps }: AppProps) => {
      let location = useLocation();
    
      useEffect(() => {
    
        alert(location );// this will be called whenever the route changes 
    
      }, [location ]);
      return (
        <>
          <Child>
            <Component {...pageProps} />
          </Child>
        </>
      );
    };
    export default App;
    

    【讨论】:

    • 嗨,这确实需要使用 react-router-dom + 它在 nextJS TypeError 中给出错误:无法读取未定义的属性“位置”。
    • 是的,你需要 eact-router-dom
    • 对不起,我完全忽略了你问题的 Nextjs 部分,但仍然尝试 react-router-dom
    • 您引用了useLocation,但没有指定使其可用或定义它的包
    【解决方案2】:

    您可以在路线发生变化时使用routeChangeStartrouteChangeCompleterouteChangeError 事件来执行某些功能。

    这里我使用 NProgress 来显示细长的进度条,如果你愿意,你可以尝试同样的事情并了解它是如何工作的,或者你可以只记录一些数据,() =&gt; { console.log("route change start") }

    import '../styles/globals.css'
    import 'nprogress/nprogress.css'
    import NProgress from 'nprogress'
    import { Router } from 'next/dist/client/router'
    Router.events.on('routeChangeStart', () => {
      NProgress.start()
    })
    Router.events.on('routeChangeComplete', () => {
      NProgress.done()
    })
    Router.events.on('routeChangeError', () => {
      NProgress.done()
    })
    function MyApp({ Component, pageProps }) {
      return (
        <div>
          <h1 style={{ textAlign: 'center', alignItems: 'center' }}>
            Welcome to my App
          </h1>
          <Component {...pageProps} />
        </div>
      )
    }
    
    export default MyApp
    

    【讨论】:

    • @Maxime Ghéraille,您可能不需要使用 useEffect,因为如果您在 _app.js 中使用路由更改,它会在每次路由更改时自动渲染,我从自己的应用程序中注意到它,我只是推荐你试着告诉我它是否有效,谢谢,如果它有效,你可以将我的帖子标记为答案吗?谢谢
    【解决方案3】:

    感谢@Faruk 的回答,我发现这是可能的,但我不得不在我的钩子中使用那些 router.events.on。

    useEffect(() => {
        router.events.on("routeChangeComplete", () => {
          console.log("route change routeChangeComplete");
        });
        return () => {
          router.events.off("routeChangeComplete", () => {
            console.log("stoped");
          });
        };
      }, [router.events]);
    

    【讨论】:

      【解决方案4】:

      通过监听router.asPath 的变化,我能够更简单地完成这项工作。

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

      【讨论】:

        【解决方案5】:
        import  { useRouter } from "next/router";
        import { useEffect, useState } from "react";
        
        const App = ({ }) => {
          const router = useRouter(),
          [ready, setReady] = useState(false);
        
          const enableReady = async (loc) => {
          setReady(false);
          console.log("enableReady", loc);
        };
        
        const disableReady = async (loc) => {
          console.log(".....");
          await sleep(3);
          console.log("done");
          setReady(true);
          console.log("disableReady", loc);
        };
        
        useEffect(() => {
          router.events.on("routeChangeStart", async () => await enableReady("star a"));
          router.events.on("routeChangeComplete", async () => await disableReady("com a"));
          router.events.on("routeChangeError", async () => await disableReady("err a"));
        
          return () => {
            router.events.off("routeChangeStart", async () => await enableReady("star b"));
            router.events.off("routeChangeComplete", async () => await disableReady("com b"));
            router.events.off("routeChangeError", async () => await disableReady("err b"));
          };
        }, [router.events]);
        
        }
        

        【讨论】:

          猜你喜欢
          • 2017-06-14
          • 1970-01-01
          • 1970-01-01
          • 2021-06-16
          • 2021-04-29
          • 1970-01-01
          • 2021-11-11
          • 2021-08-13
          • 1970-01-01
          相关资源
          最近更新 更多