主题
useRouter
如果你想访问应用中任何功能组件内的 router 对象,你可以使用 useRouter 钩子,请看以下示例:
¥If you want to access the router object inside any function component in your app, you can use the useRouter hook, take a look at the following example:
useRouter是 React 钩子,这意味着它不能与类一起使用。你可以使用 withRouter 或将你的类封装在函数组件中。¥
useRouteris a React Hook, meaning it cannot be used with classes. You can either use withRouter or wrap your class in a function component.
router 对象
¥router object
以下是 useRouter 和 withRouter 返回的 router 对象的定义:
¥The following is the definition of the router object returned by both useRouter and withRouter:
pathname:String-/pages之后的当前路由文件的路径。因此,不包括basePath、locale和尾部斜杠 (trailingSlash: true)。¥
pathname:String- The path for current route file that comes after/pages. Therefore,basePath,localeand trailing slash (trailingSlash: true) are not included.query:Object- 查询字符串解析为对象,包含 动态路由 个参数。如果页面不使用 服务端渲染,则在预渲染期间它将是一个空对象。默认为{}¥
query:Object- The query string parsed to an object, including dynamic route parameters. It will be an empty object during prerendering if the page doesn't use Server-side Rendering. Defaults to{}asPath:String- 浏览器中显示的路径包括搜索参数并遵循trailingSlash配置。不包括basePath和locale。¥
asPath:String- The path as shown in the browser including the search params and respecting thetrailingSlashconfiguration.basePathandlocaleare not included.isFallback:boolean- 当前页面是否在 后备模式。¥
isFallback:boolean- Whether the current page is in fallback mode.basePath:String- 活动 basePath(如果启用)。¥
basePath:String- The active basePath (if enabled).locale:String- 活动区域设置(如果启用)。¥
locale:String- The active locale (if enabled).locales:String[]- 所有受支持的区域设置(如果启用)。¥
locales:String[]- All supported locales (if enabled).defaultLocale:String- 当前的默认区域设置(如果启用)。¥
defaultLocale:String- The current default locale (if enabled).domainLocales:Array<{domain, defaultLocale, locales}>- 任何配置的域语言环境。¥
domainLocales:Array<{domain, defaultLocale, locales}>- Any configured domain locales.isReady:boolean- 路由字段是否已在客户端更新并可供使用。只能在useEffect方法内部使用,不能用于服务器上的条件渲染。请参阅相关文档了解 自动静态优化页面 的用例¥
isReady:boolean- Whether the router fields are updated client-side and ready for use. Should only be used inside ofuseEffectmethods and not for conditionally rendering on the server. See related docs for use case with automatically statically optimized pagesisPreview:boolean- 应用当前是否处于 预览模式。¥
isPreview:boolean- Whether the application is currently in preview mode.
如果页面使用服务器端渲染或 自动静态优化 渲染,则使用
asPath字段可能会导致客户端和服务器之间不匹配。在isReady字段为true之前,避免使用asPath。¥Using the
asPathfield may lead to a mismatch between client and server if the page is rendered using server-side rendering or automatic static optimization. Avoid usingasPathuntil theisReadyfield istrue.
router 内部包含以下方法:
¥The following methods are included inside router:
router.push
处理客户端转换,此方法对于 next/link 不够的情况很有用。
¥Handles client-side transitions, this method is useful for cases where next/link is not enough.
url:UrlObject | String- 要导航到的 URL(请参阅 Node.JS URL 模块文档 了解UrlObject属性)。¥
url:UrlObject | String- The URL to navigate to (see Node.JS URL module documentation forUrlObjectproperties).as:UrlObject | String- 将显示在浏览器 URL 栏中的路径的可选装饰器。在 Next.js 9.5.3 之前,这用于动态路由。¥
as:UrlObject | String- Optional decorator for the path that will be shown in the browser URL bar. Before Next.js 9.5.3 this was used for dynamic routes.options- 具有以下配置选项的可选对象:¥
options- Optional object with the following configuration options:scroll- 可选布尔值,控制导航后滚动到页面顶部。默认为true¥
scroll- Optional boolean, controls scrolling to the top of the page after navigation. Defaults totrueshallow:更新当前页面的路径,无需重新运行getStaticProps、getServerSideProps或getInitialProps。默认为false¥
shallow: Update the path of the current page without rerunninggetStaticProps,getServerSidePropsorgetInitialProps. Defaults tofalselocale- 可选字符串,指示新页面的区域设置¥
locale- Optional string, indicates locale of the new page
你不需要将
router.push用于外部 URL。window.location 更适合这些情况。¥You don't need to use
router.pushfor external URLs. window.location is better suited for those cases.
导航到 pages/about.js,这是预定义的路由:
¥Navigating to pages/about.js, which is a predefined route:
导航 pages/post/[pid].js,这是一条动态路由:
¥Navigating pages/post/[pid].js, which is a dynamic route:
将用户重定向到 pages/login.js,对于 authentication 后面的页面很有用:
¥Redirecting the user to pages/login.js, useful for pages behind authentication:
导航后重置状态
¥Resetting state after navigation
当导航到 Next.js 中的同一页面时,默认情况下不会重置页面的状态,因为除非父组件发生更改,否则 React 不会卸载。
¥When navigating to the same page in Next.js, the page's state will not be reset by default as React does not unmount unless the parent component has changed.
在上面的示例中,在 /one 和 /two 之间导航不会重置计数。 useState 在渲染之间保持不变,因为顶层 React 组件 Page 是相同的。
¥In the above example, navigating between /one and /two will not reset the count . The useState is maintained between renders because the top-level React component, Page, is the same.
如果你不希望出现这种行为,你有以下几种选择:
¥If you do not want this behavior, you have a couple of options:
使用
useEffect手动确保每个状态都已更新。在上面的示例中,可能如下所示:¥Manually ensure each state is updated using
useEffect. In the above example, that could look like:使用 React
key到 告诉 React 重新挂载组件。要对所有页面执行此操作,你可以使用自定义应用:¥Use a React
keyto tell React to remount the component. To do this for all pages, you can use a custom app:
带有 URL 对象
¥With URL object
你可以按照与 next/link 相同的方式使用 URL 对象。适用于 url 和 as 参数:
¥You can use a URL object in the same way you can use it for next/link. Works for both the url and as parameters:
router.replace
与 next/link 中的 replace 属性类似,router.replace 将阻止向 history 堆栈中添加新的 URL 条目。
¥Similar to the replace prop in next/link, router.replace will prevent adding a new URL entry into the history stack.
router.replace的 API 与router.push的 API 完全相同。¥The API for
router.replaceis exactly the same as the API forrouter.push.
看一下下面的例子:
¥Take a look at the following example:
router.prefetch
预取页面以实现更快的客户端转换。此方法仅适用于没有 next/link 的导航,因为 next/link 会自动处理预取页面。
¥Prefetch pages for faster client-side transitions. This method is only useful for navigations without next/link, as next/link takes care of prefetching pages automatically.
这是仅限生产的功能。Next.js 在开发中不会预取页面。
¥This is a production only feature. Next.js doesn't prefetch pages in development.
url- 要预取的 URL,包括显式路由(例如/dashboard)和动态路由(例如/product/[id])¥
url- The URL to prefetch, including explicit routes (e.g./dashboard) and dynamic routes (e.g./product/[id])as-url的可选装饰器。在 Next.js 9.5.3 之前,这用于预取动态路由。¥
as- Optional decorator forurl. Before Next.js 9.5.3 this was used to prefetch dynamic routes.options- 具有以下允许字段的可选对象:¥
options- Optional object with the following allowed fields:locale- 允许提供与活动区域不同的区域设置。如果false、url必须包含区域设置,因为不会使用活动区域设置。¥
locale- allows providing a different locale from the active one. Iffalse,urlhas to include the locale as the active locale won't be used.
假设你有一个登录页面,登录后,你将用户重定向到仪表板。对于这种情况,我们可以预取仪表板以实现更快的转换,如下例所示:
¥Let's say you have a login page, and after a login, you redirect the user to the dashboard. For that case, we can prefetch the dashboard to make a faster transition, like in the following example:
router.beforePopState
在某些情况下(例如,如果使用 自定义服务器),你可能希望监听 popstate 并在路由对其进行操作之前执行某些操作。
¥In some cases (for example, if using a Custom Server), you may wish to listen to popstate and do something before the router acts on it.
cb- 在传入popstate事件时运行的函数。该函数将事件状态作为具有以下属性的对象接收:¥
cb- The function to run on incomingpopstateevents. The function receives the state of the event as an object with the following props:url:String- 新状态的路由。这通常是page的名字¥
url:String- the route for the new state. This is usually the name of apageas:String- 将在浏览器中显示的 url¥
as:String- the url that will be shown in the browseroptions:Object- router.push 发送的附加选项¥
options:Object- Additional options sent by router.push
如果 cb 返回 false,Next.js 路由将不会处理 popstate,在这种情况下你将负责处理它。查看 禁用文件系统路由。
¥If cb returns false, the Next.js router will not handle popstate, and you'll be responsible for handling it in that case. See Disabling file-system routing.
你可以使用 beforePopState 来操纵请求,或强制 SSR 刷新,如下例所示:
¥You could use beforePopState to manipulate the request, or force a SSR refresh, as in the following example:
router.back
在历史记录中向后导航。相当于点击浏览器的后退按钮。它执行 window.history.back()。
¥Navigate back in history. Equivalent to clicking the browser’s back button. It executes window.history.back().
router.reload
重新加载当前 URL。相当于点击浏览器的刷新按钮。它执行 window.location.reload()。
¥Reload the current URL. Equivalent to clicking the browser’s refresh button. It executes window.location.reload().
router.events
你可以监听 Next.js Router 内发生的不同事件。以下是支持的事件列表:
¥You can listen to different events happening inside the Next.js Router. Here's a list of supported events:
routeChangeStart(url, { shallow })- 当路由开始改变时触发¥
routeChangeStart(url, { shallow })- Fires when a route starts to changerouteChangeComplete(url, { shallow })- 当路由完全改变时触发¥
routeChangeComplete(url, { shallow })- Fires when a route changed completelyrouteChangeError(err, url, { shallow })- 当更改路由时出现错误或路由加载被取消时触发¥
routeChangeError(err, url, { shallow })- Fires when there's an error when changing routes, or a route load is cancellederr.cancelled- 指示导航是否已取消¥
err.cancelled- Indicates if the navigation was cancelled
beforeHistoryChange(url, { shallow })- 在更改浏览器历史记录之前触发¥
beforeHistoryChange(url, { shallow })- Fires before changing the browser's historyhashChangeStart(url, { shallow })- 当哈希值发生变化但页面不变时触发¥
hashChangeStart(url, { shallow })- Fires when the hash will change but not the pagehashChangeComplete(url, { shallow })- 当哈希值已更改但页面未更改时触发¥
hashChangeComplete(url, { shallow })- Fires when the hash has changed but not the page
需要了解:这里的
url是浏览器中显示的 URL,包括basePath。¥Good to know: Here
urlis the URL shown in the browser, including thebasePath.
例如,要监听路由事件 routeChangeStart,请打开或创建 pages/_app.js 并订阅该事件,如下所示:
¥For example, to listen to the router event routeChangeStart, open or create pages/_app.js and subscribe to the event, like so:
我们在本示例中使用 自定义应用 (
pages/_app.js) 来订阅事件,因为它不会在页面导航上卸载,但你可以在应用中的任何组件上订阅路由事件。¥We use a Custom App (
pages/_app.js) for this example to subscribe to the event because it's not unmounted on page navigations, but you can subscribe to router events on any component in your application.
路由事件应在组件安装(useEffect 或 componentDidMount / componentWillUnmount)时注册,或者在事件发生时强制注册。
¥Router events should be registered when a component mounts (useEffect or componentDidMount / componentWillUnmount) or imperatively when an event happens.
如果路由加载被取消(例如,通过连续快速单击两个链接),routeChangeError 将触发。并且传递的 err 将包含设置为 true 的 cancelled 属性,如下例所示:
¥If a route load is cancelled (for example, by clicking two links rapidly in succession), routeChangeError will fire. And the passed err will contain a cancelled property set to true, as in the following example:
next/compat/router 导出
¥The next/compat/router export
这是相同的 useRouter 钩子,但可以在 app 和 pages 目录中使用。
¥This is the same useRouter hook, but can be used in both app and pages directories.
它与 next/router 的不同之处在于,当未安装页面路由时,它不会抛出错误,而是具有返回类型 NextRouter | null。这允许开发者在过渡到 app 路由时转换组件以支持在 app 和 pages 中运行。
¥It differs from next/router in that it does not throw an error when the pages router is not mounted, and instead has a return type of NextRouter | null. This allows developers to convert components to support running in both app and pages as they transition to the app router.
以前看起来像这样的组件:
¥A component that previously looked like this:
转换为 next/compat/router 时会出错,因为 null 无法解构。相反,开发者将能够利用新的钩子:
¥Will error when converted over to next/compat/router, as null can not be destructured. Instead, developers will be able to take advantage of new hooks:
此组件现在可在 pages 和 app 目录中工作。当组件不再在 pages 中使用时,你可以删除对兼容路由的引用:
¥This component will now work in both pages and app directories. When the component is no longer used in pages, you can remove the references to the compat router:
在页面中的 Next.js 上下文之外使用 useRouter
¥Using useRouter outside of Next.js context in pages
另一个特定用例是在 Next.js 应用上下文之外渲染组件时,例如在 pages 目录上的 getServerSideProps 内部。在这种情况下,可以使用兼容路由来避免错误:
¥Another specific use case is when rendering components outside of a Next.js application context, such as inside getServerSideProps on the pages directory. In this case, the compat router can be used to avoid errors:
潜在的 ESLint 错误
¥Potential ESLint errors
router 对象上可访问的某些方法会返回 Promise。如果你启用了 ESLint 规则 no-floating-promises,请考虑全局禁用它或针对受影响的行禁用它。
¥Certain methods accessible on the router object return a Promise. If you have the ESLint rule, no-floating-promises enabled, consider disabling it either globally, or for the affected line.
如果你的应用需要此规则,你应该 void promise - 或使用 async 函数,await promise,然后无效函数调用。当从 onClick 处理程序内部调用该方法时,这不适用。
¥If your application needs this rule, you should either void the promise – or use an async function, await the Promise, then void the function call. This is not applicable when the method is called from inside an onClick handler.
受影响的方法是:
¥The affected methods are:
router.pushrouter.replacerouter.prefetch
潜在的解决方案
¥Potential solutions
withRouter
如果 useRouter 不是最适合你,withRouter 也可以将相同的 router 对象 添加到任何组件。
¥If useRouter is not the best fit for you, withRouter can also add the same router object to any component.
用法
¥Usage
TypeScript
要将类组件与 withRouter 一起使用,该组件需要接受 router 属性:
¥To use class components with withRouter, the component needs to accept a router prop:
tsx
import React from 'react'
import { withRouter, NextRouter } from 'next/router'
interface WithRouterProps {
router: NextRouter
}
interface MyComponentProps extends WithRouterProps {}
class MyComponent extends React.Component<MyComponentProps> {
render() {
return <p>{this.props.router.pathname}</p>
}
}
export default withRouter(MyComponent)