如何在nextjs的this.props中获取历史和匹配?

Log*_*ari 2 next.js next-router

我想在 this.props 中获取历史和匹配的值。我正在使用next/router导入withRouter. 我想使用 this.props.match.params 来获取 url 中的值并history.push重定向。如何在 Next.js 中得到这个。现在我没有在 this.props 中获取历史和匹配。

Anu*_*thi 6

next/router不提供历史记录,但我们可以使用next router.events来获取全局级别的先前路径和当前路径。

参考

_app.js

import {useEffect} from "react"
import { useRouter } from 'next/router'


let prevRoute
let currentRoute
const MyApp = ({ Component, pageProps }) => {
    const router = useRouter()
    currentRoute = router.pathname
    
    // THAT'S THE MAIN WORKAROUND
    
    useEffect(() => {
        const handleRouteChange = (url, { shallow }) => {
            prevRoute = currentRoute
            currentRoute = url
            console.log(prevRoute, currentRoute)
        }
        router.events.on('routeChangeStart', handleRouteChange)

        // If the component is unmounted, unsubscribe
        // from the event with the `off` method:
        return () => {
            router.events.off('routeChangeStart', handleRouteChange)
        }
    }, [])
    
    
    
    
    return (
        <>
            <Component prevRoute={prevRoute} currentRoute={currentRoute} {...pageProps} />
        </>
    );
};
export default MyApp;
Run Code Online (Sandbox Code Playgroud)


Sul*_* H. 5

next/router不像那样为您提供历史记录react-dom-router,它在您的组件的props.

这是官方的用法示例

import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const { pid } = router.query

  return <p>Post: {pid}</p>
}

export default Post
Run Code Online (Sandbox Code Playgroud)

如果你想推送路由,你可以按照这个。例子

import Router from 'next/router'

function ReadMore() {
  return (
    <div>
      Click <span onClick={() => Router.push('/about')}>here</span> to read more
    </div>
  )
}

export default ReadMore
Run Code Online (Sandbox Code Playgroud)


dim*_*sus 5

编辑:我不得不回到全局路由器。useRouter 钩子不起作用,因为它的生命周期似乎不同,因此我无法在给定时间获取我需要的确切值。

.....
    if (
      !shallow &&
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(Router.asPath)) &&
      nextUrl !== Router.asPath
    ) {
      setPreviousRoute(Router.asPath);
    }
  };

  useEffect(() => {
    Router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      Router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);

  return { previousRoute };
};
Run Code Online (Sandbox Code Playgroud)

编辑:由于全局路由器对象污染不是一件好事,您可以使用状态变量代替:

const EXCEPTIONS = ['/sign-up'];

/**
 * Saves the current URL before changing the route.
 */
const useRouteUrlHistory = () => {
  const [previousRoute, setPreviousRouter] = useState('');
  const router = useRouter();

  const handleBeforeHistoryChange = (url) => {
    const [nextUrl] = url?.split('?') || [];

    if (
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(router.asPath)) &&
      nextUrl !== router.asPath
    ) {
      setPreviousRouter(router.asPath);
    }
  };

  useEffect(() => {
    router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);

  return { previousRoute };
};

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

您必须在 _app.js 中使用钩子,因为您要侦听路由更改并希望全局保存/访问 previousRoute。

const MyApp = ({ Component, pageProps }) => {

  const { previousRoute } = useRouteUrlHistory();

  return (
        <ApplicationContext.Provider
          value={{
            previousRoute,
            ... another global context
          }}
        >
           ... components etc.
        </ApplicationContext.Provider>
Run Code Online (Sandbox Code Playgroud)

======

我还没有找到一种能够完整访问 Router.history 的优雅方式。但通常情况下,我想至少访问上次访问的路线,这迫使我采用这种解决方法。这可能不是最优雅的方式,因为它会污染全局 Router 对象,但正如我所说,我还没有找到任何替代方案。

我只检查以前访问过的实际路线。您还可以实现您的逻辑来检查参数。在路由器处理实际路由更改之前的钩子插件。这允许您在应用程序中收听 Router.previousRoute 属性。

请记住,如果您进行浅层路由,您可能不会影响 Router.history,这可能不会触发此事件挂钩。

const EXCEPTIONS = ['/sign-up'];

/**
 * Saves the current URL before changing the route.
 * The previousRoute is then accessible via the global Router.
 */
const useRouteUrlHistory = () => {
  const handleBeforeHistoryChange = (url) => {
    const [nextUrl] = url?.split('?') || [];

    if (
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(Router.asPath)) &&
      nextUrl !== Router.asPath
    ) {
      Router.previousRoute = Router.asPath;
    }
  };

  useEffect(() => {
    Router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      Router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);
};

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