导航

一切都是相对的

信不信由你,应用程序中的每次导航都是相对的,即使您没有使用显式的相对路径语法 (../../somewhere)。 任何时候点击链接或发出命令式导航调用,您都将始终拥有一个路径和一个目标路径,这意味着您正在一个路由导航另一个路由。

TanStack Router 在每次导航中都牢记相对导航的这个恒定概念,因此您将经常在 API 中看到两个属性

  • from - 源路由路径
  • to - 目标路由路径

⚠️ 如果未提供 from 路由路径,则路由器将假定您从根 / 路由导航,并且仅自动完成绝对路径。 毕竟,您需要知道您从哪里来才能知道您要去哪里 😉。

共享导航 API

TanStack Router 中的每个导航和路由匹配 API 都使用相同的核心接口,但 API 之间存在细微差异。 这意味着您可以学习一次导航和路由匹配,并在整个库中使用相同的语法和概念。

ToOptions 接口

这是核心 ToOptions 接口,用于每个导航和路由匹配 API

ts
type ToOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = {
  // `from` is an optional route ID or path. If it is not supplied, only absolute paths will be auto-completed and type-safe. It's common to supply the route.fullPath of the origin route you are rendering from for convenience. If you don't know the origin route, leave this empty and work with absolute paths or unsafe relative paths.
  from: string
  // `to` can be an absolute route path or a relative path from the `from` option to a valid route path. ⚠️ Do not interpolate path params, hash or search params into the `to` options. Use the `params`, `search`, and `hash` options instead.
  to: string
  // `params` is either an object of path params to interpolate into the `to` option or a function that supplies the previous params and allows you to return new ones. This is the only way to interpolate dynamic parameters into the final URL. Depending on the `from` and `to` route, you may need to supply none, some or all of the path params. TypeScript will notify you of the required params if there are any.
  params:
    | Record<string, unknown>
    | ((prevParams: Record<string, unknown>) => Record<string, unknown>)
  // `search` is either an object of query params or a function that supplies the previous search and allows you to return new ones. Depending on the `from` and `to` route, you may need to supply none, some or all of the query params. TypeScript will notify you of the required search params if there are any.
  search:
    | Record<string, unknown>
    | ((prevSearch: Record<string, unknown>) => Record<string, unknown>)
  // `hash` is either a string or a function that supplies the previous hash and allows you to return a new one.
  hash?: string | ((prevHash: string) => string)
  // `state` is either an object of state or a function that supplies the previous state and allows you to return a new one. State is stored in the history API and can be useful for passing data between routes that you do not want to permanently store in URL search params.
  state?:
    | Record<string, any>
    | ((prevState: Record<string, unknown>) => Record<string, unknown>)
}
type ToOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = {
  // `from` is an optional route ID or path. If it is not supplied, only absolute paths will be auto-completed and type-safe. It's common to supply the route.fullPath of the origin route you are rendering from for convenience. If you don't know the origin route, leave this empty and work with absolute paths or unsafe relative paths.
  from: string
  // `to` can be an absolute route path or a relative path from the `from` option to a valid route path. ⚠️ Do not interpolate path params, hash or search params into the `to` options. Use the `params`, `search`, and `hash` options instead.
  to: string
  // `params` is either an object of path params to interpolate into the `to` option or a function that supplies the previous params and allows you to return new ones. This is the only way to interpolate dynamic parameters into the final URL. Depending on the `from` and `to` route, you may need to supply none, some or all of the path params. TypeScript will notify you of the required params if there are any.
  params:
    | Record<string, unknown>
    | ((prevParams: Record<string, unknown>) => Record<string, unknown>)
  // `search` is either an object of query params or a function that supplies the previous search and allows you to return new ones. Depending on the `from` and `to` route, you may need to supply none, some or all of the query params. TypeScript will notify you of the required search params if there are any.
  search:
    | Record<string, unknown>
    | ((prevSearch: Record<string, unknown>) => Record<string, unknown>)
  // `hash` is either a string or a function that supplies the previous hash and allows you to return a new one.
  hash?: string | ((prevHash: string) => string)
  // `state` is either an object of state or a function that supplies the previous state and allows you to return a new one. State is stored in the history API and can be useful for passing data between routes that you do not want to permanently store in URL search params.
  state?:
    | Record<string, any>
    | ((prevState: Record<string, unknown>) => Record<string, unknown>)
}

🧠 每个路由对象都有一个 to 属性,可以用作任何导航或路由匹配 API 的 to。 在可能的情况下,这将允许您避免使用纯字符串,而是使用类型安全的路由引用。

tsx
import { Route as aboutRoute } from './routes/about.tsx'

function Comp() {
  return <Link to={aboutRoute.to}>About</Link>
}
import { Route as aboutRoute } from './routes/about.tsx'

function Comp() {
  return <Link to={aboutRoute.to}>About</Link>
}

这是核心 NavigateOptions 接口,它扩展了 ToOptions。 任何实际执行导航的 API 都将使用此接口。

ts
export type NavigateOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = ToOptions<TRouteTree, TFrom, TTo> & {
  // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
  replace?: boolean
  // `resetScroll` is a boolean that determines whether scroll position will be reset to 0,0 after the location is committed to browser history.
  resetScroll?: boolean
  // `hashScrollIntoView` is a boolean or object that determines whether an id matching the hash will be scrolled into view after the location is committed to history.
  hashScrollIntoView?: boolean | ScrollIntoViewOptions
  // `viewTransition` is either a boolean or function that determines if and how the browser will call document.startViewTransition() when navigating.
  viewTransition?: boolean | ViewTransitionOptions
  // `ignoreBlocker` is a boolean that determines if navigation should ignore any blockers that might prevent it.
  ignoreBlocker?: boolean
  // `reloadDocument` is a boolean that determines if navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.
  reloadDocument?: boolean
  // `href` is a string that can be used in place of `to` to navigate to a full built href, e.g. pointing to an external target.
  href?: string
}
export type NavigateOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = ToOptions<TRouteTree, TFrom, TTo> & {
  // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
  replace?: boolean
  // `resetScroll` is a boolean that determines whether scroll position will be reset to 0,0 after the location is committed to browser history.
  resetScroll?: boolean
  // `hashScrollIntoView` is a boolean or object that determines whether an id matching the hash will be scrolled into view after the location is committed to history.
  hashScrollIntoView?: boolean | ScrollIntoViewOptions
  // `viewTransition` is either a boolean or function that determines if and how the browser will call document.startViewTransition() when navigating.
  viewTransition?: boolean | ViewTransitionOptions
  // `ignoreBlocker` is a boolean that determines if navigation should ignore any blockers that might prevent it.
  ignoreBlocker?: boolean
  // `reloadDocument` is a boolean that determines if navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.
  reloadDocument?: boolean
  // `href` is a string that can be used in place of `to` to navigate to a full built href, e.g. pointing to an external target.
  href?: string
}

LinkOptions 接口

任何实际的 <a> 标签,扩展了 NavigateOptionsLinkOptions 接口都将可用。

tsx
export type LinkOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = NavigateOptions<TRouteTree, TFrom, TTo> & {
  // The standard anchor tag target attribute
  target?: HTMLAnchorElement['target']
  // Defaults to `{ exact: false, includeHash: false }`
  activeOptions?: {
    exact?: boolean
    includeHash?: boolean
    includeSearch?: boolean
    explicitUndefined?: boolean
  }
  // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
  preload?: false | 'intent'
  // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
  preloadDelay?: number
  // If true, will render the link without the href attribute
  disabled?: boolean
}
export type LinkOptions<
  TRouteTree extends AnyRoute = AnyRoute,
  TFrom extends RoutePaths<TRouteTree> | string = string,
  TTo extends string = '',
> = NavigateOptions<TRouteTree, TFrom, TTo> & {
  // The standard anchor tag target attribute
  target?: HTMLAnchorElement['target']
  // Defaults to `{ exact: false, includeHash: false }`
  activeOptions?: {
    exact?: boolean
    includeHash?: boolean
    includeSearch?: boolean
    explicitUndefined?: boolean
  }
  // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
  preload?: false | 'intent'
  // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
  preloadDelay?: number
  // If true, will render the link without the href attribute
  disabled?: boolean
}

现在我们已经了解了相对导航和所有接口,让我们来谈谈您可用的不同类型的导航 API。

  • <Link> 组件
    • 生成一个实际的 <a> 标签,其中包含有效的 href,可以单击甚至 cmd/ctrl + 单击以在新标签页中打开。
  • useNavigate() Hook
    • 在可能的情况下,应使用 Link 组件进行导航,但有时您需要由于副作用而命令式地导航。 useNavigate 返回一个可以调用的函数,以执行立即的客户端导航。
  • <Navigate> 组件
    • 不渲染任何内容并执行立即的客户端导航。
  • Router.navigate() 方法
    • 这是 TanStack Router 中最强大的导航 API。 与 useNavigate 类似,它以命令方式导航,但在您可以访问路由器的任何地方都可用。

⚠️ 这些 API 都不能替代服务器端重定向。 如果您需要在挂载应用程序之前立即将用户从一个路由重定向到另一个路由,请使用服务器端重定向而不是客户端导航。

Link 组件是在应用程序中最常见的导航方式。 它渲染一个实际的 <a> 标签,其中包含有效的 href 属性,可以单击甚至 cmd/ctrl + 单击以在新标签页中打开。 它还支持任何正常的 <a> 属性,包括 target 以在新窗口中打开链接等。

除了 LinkOptions 接口之外,Link 组件还支持以下 props

tsx
export type LinkProps<
  TFrom extends RoutePaths<RegisteredRouter['routeTree']> | string = string,
  TTo extends string = '',
> = LinkOptions<RegisteredRouter['routeTree'], TFrom, TTo> & {
  // A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
  activeProps?:
    | FrameworkHTMLAnchorTagAttributes
    | (() => FrameworkHTMLAnchorAttributes)
  // A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
  inactiveProps?:
    | FrameworkHTMLAnchorAttributes
    | (() => FrameworkHTMLAnchorAttributes)
}
export type LinkProps<
  TFrom extends RoutePaths<RegisteredRouter['routeTree']> | string = string,
  TTo extends string = '',
> = LinkOptions<RegisteredRouter['routeTree'], TFrom, TTo> & {
  // A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
  activeProps?:
    | FrameworkHTMLAnchorTagAttributes
    | (() => FrameworkHTMLAnchorAttributes)
  // A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
  inactiveProps?:
    | FrameworkHTMLAnchorAttributes
    | (() => FrameworkHTMLAnchorAttributes)
}

让我们创建一个简单的静态链接!

tsx
import { Link } from '@tanstack/solid-router'

const link = <Link to="/about">About</Link>
import { Link } from '@tanstack/solid-router'

const link = <Link to="/about">About</Link>

动态链接是其中包含动态段的链接。 例如,指向博客文章的链接可能如下所示

tsx
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
  >
    Blog Post
  </Link>
)
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
  >
    Blog Post
  </Link>
)

请记住,通常动态段参数是 string 值,但它们也可以是您在路由选项中解析为的任何其他类型。 无论哪种方式,类型都会在编译时进行检查,以确保您传递的是正确的类型。

默认情况下,除非提供 from 路由路径,否则所有链接都是绝对的。 这意味着无论您当前在哪个路由上,上面的链接都将始终导航到 /about 路由。

如果您想创建一个相对于当前路由的链接,您可以提供一个 from 路由路径

tsx
const postIdRoute = createRoute({
  path: '/blog/post/$postId',
})

const link = (
  <Link from={postIdRoute.fullPath} to="../categories">
    Categories
  </Link>
)
const postIdRoute = createRoute({
  path: '/blog/post/$postId',
})

const link = (
  <Link from={postIdRoute.fullPath} to="../categories">
    Categories
  </Link>
)

如上所示,通常提供 route.fullPath 作为 from 路由路径。 这是因为 route.fullPath 是一个引用,如果您重构应用程序,它将更新。 但是,有时不可能直接导入路由,在这种情况下,可以直接将路由路径作为字符串提供。 它仍然会像往常一样进行类型检查!

查询参数是为路由提供额外上下文的好方法。 例如,您可能想为搜索页面提供搜索查询

tsx
const link = (
  <Link
    to="/search"
    search={{
      query: 'tanstack',
    }}
  >
    Search
  </Link>
)
const link = (
  <Link
    to="/search"
    search={{
      query: 'tanstack',
    }}
  >
    Search
  </Link>
)

也很常见的是想要更新单个查询参数,而无需提供有关现有路由的任何其他信息。 例如,您可能想要更新搜索结果的页码

tsx
const link = (
  <Link
    to="."
    search={(prev) => ({
      ...prev,
      page: prev.page + 1,
    })}
  >
    Next Page
  </Link>
)
const link = (
  <Link
    to="."
    search={(prev) => ({
      ...prev,
      page: prev.page + 1,
    })}
  >
    Next Page
  </Link>
)

查询参数类型安全

查询参数是一种高度动态的状态管理机制,因此确保您将正确的类型传递给查询参数非常重要。 我们将在后面的章节中详细了解如何验证和确保查询参数的类型安全以及其他出色的功能!

Hash 链接是链接到页面特定部分的好方法。 例如,您可能想要链接到博客文章的特定部分

tsx
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
    hash="section-1"
  >
    Section 1
  </Link>
)
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
    hash="section-1"
  >
    Section 1
  </Link>
)

Active & Inactive Props

Link 组件支持两个额外的 props:activePropsinactiveProps。 这些 props 是返回链接的 activeinactive 状态的额外 props 的函数。 除此处传递的样式和类之外的所有 props 都将覆盖传递给 Link 的原始 props。 任何传递的样式或类都会合并在一起。

这是一个例子

tsx
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
    activeProps={{
      style: {
        fontWeight: 'bold',
      },
    }}
  >
    Section 1
  </Link>
)
const link = (
  <Link
    to="/blog/post/$postId"
    params={{
      postId: 'my-first-blog-post',
    }}
    activeProps={{
      style: {
        fontWeight: 'bold',
      },
    }}
  >
    Section 1
  </Link>
)

The data-status 属性

除了 activePropsinactiveProps props 之外,当 Link 组件处于活动状态时,它还会向渲染的元素添加 data-status 属性。 此属性将为 activeundefined,具体取决于链接的当前状态。 如果您喜欢使用 data-attributes 而不是 props 来设置链接样式,这将非常方便。

Active Options

Link 组件带有一个 activeOptions 属性,该属性提供了一些用于确定链接是否处于活动状态的选项。 以下接口描述了这些选项

tsx
export interface ActiveOptions {
  // If true, the link will be active if the current route matches the `to` route path exactly (no children routes)
  // Defaults to `false`
  exact?: boolean
  // If true, the link will only be active if the current URL hash matches the `hash` prop
  // Defaults to `false`
  includeHash?: boolean // Defaults to false
  // If true, the link will only be active if the current URL search params inclusively match the `search` prop
  // Defaults to `true`
  includeSearch?: boolean
  // This modifies the `includeSearch` behavior.
  // If true,  properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.
  // defaults to `false`
  explicitUndefined?: boolean
}
export interface ActiveOptions {
  // If true, the link will be active if the current route matches the `to` route path exactly (no children routes)
  // Defaults to `false`
  exact?: boolean
  // If true, the link will only be active if the current URL hash matches the `hash` prop
  // Defaults to `false`
  includeHash?: boolean // Defaults to false
  // If true, the link will only be active if the current URL search params inclusively match the `search` prop
  // Defaults to `true`
  includeSearch?: boolean
  // This modifies the `includeSearch` behavior.
  // If true,  properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.
  // defaults to `false`
  explicitUndefined?: boolean
}

默认情况下,它将检查结果 pathname 是否是当前路由的前缀。 如果提供了任何查询参数,它将检查它们是否 包含性地 匹配当前位置的查询参数。 默认情况下不检查哈希值。

例如,如果您在 /blog/post/my-first-blog-post 路由上,则以下链接将处于活动状态

tsx
const link1 = (
  <Link to="/blog/post/$postId" params={{ postId: 'my-first-blog-post' }}>
    Blog Post
  </Link>
)
const link2 = <Link to="/blog/post">Blog Post</Link>
const link3 = <Link to="/blog">Blog Post</Link>
const link1 = (
  <Link to="/blog/post/$postId" params={{ postId: 'my-first-blog-post' }}>
    Blog Post
  </Link>
)
const link2 = <Link to="/blog/post">Blog Post</Link>
const link3 = <Link to="/blog">Blog Post</Link>

但是,以下链接将不会处于活动状态

tsx
const link4 = (
  <Link to="/blog/post/$postId" params={{ postId: 'my-second-blog-post' }}>
    Blog Post
  </Link>
)
const link4 = (
  <Link to="/blog/post/$postId" params={{ postId: 'my-second-blog-post' }}>
    Blog Post
  </Link>
)

通常,某些链接只有在完全匹配时才处于活动状态。 首页链接就是一个很好的例子。 在这种情况下,您可以传递 exact: true 选项

tsx
const link = (
  <Link to="/" activeOptions={{ exact: true }}>
    Home
  </Link>
)
const link = (
  <Link to="/" activeOptions={{ exact: true }}>
    Home
  </Link>
)

这将确保当您是子路由时,链接不会处于活动状态。

还有一些需要注意的选项

  • 如果您想在匹配中包含哈希值,可以传递 includeHash: true 选项
  • 如果您 想在匹配中包含查询参数,可以传递 includeSearch: false 选项

isActive 传递给子组件

Link 组件接受一个函数作为其 children,允许您将其 isActive 属性传播给子组件。 例如,您可以根据父链接是否处于活动状态来设置子组件的样式

tsx
const link = (
  <Link to="/blog/post">
    {({ isActive }) => {
      return (
        <>
          <span>My Blog Post</span>
          <icon className={isActive ? 'active' : 'inactive'} />
        </>
      )
    }}
  </Link>
)
const link = (
  <Link to="/blog/post">
    {({ isActive }) => {
      return (
        <>
          <span>My Blog Post</span>
          <icon className={isActive ? 'active' : 'inactive'} />
        </>
      )
    }}
  </Link>
)

Link 组件支持在有目的时(目前为悬停或 touchstart)自动预加载路由。 这可以在路由器选项中配置为默认值(我们稍后会详细讨论),或者通过将 preload='intent' prop 传递给 Link 组件来配置。 这是一个例子

tsx
const link = (
  <Link to="/blog/post/$postId" preload="intent">
    Blog Post
  </Link>
)
const link = (
  <Link to="/blog/post/$postId" preload="intent">
    Blog Post
  </Link>
)

启用预加载和相对快速的异步路由依赖项(如果有),这个简单的技巧可以以非常小的努力提高应用程序的感知性能。

更好的是,通过使用像 @tanstack/query 这样的缓存优先库,预加载的路由将保留下来,并且如果用户稍后决定导航到该路由,则可以为 stale-while-revalidate 体验做好准备。

除了预加载之外,还有一个可配置的超时时间,它决定了用户必须将鼠标悬停在链接上多长时间才能触发基于意图的预加载。 默认超时时间为 50 毫秒,但您可以通过将 preloadTimeout prop 传递给 Link 组件来更改此时间,并指定您想要等待的毫秒数

tsx
const link = (
  <Link to="/blog/post/$postId" preload="intent" preloadTimeout={100}>
    Blog Post
  </Link>
)
const link = (
  <Link to="/blog/post/$postId" preload="intent" preloadTimeout={100}>
    Blog Post
  </Link>
)

useNavigate

⚠️ 由于 Link 组件围绕 href、cmd/ctrl + 点击能力和活动/非活动功能的内置功能,建议对于用户可以与之交互的任何内容(例如链接、按钮),都使用 Link 组件而不是 useNavigate。 但是,在某些情况下,useNavigate 是处理副作用导航所必需的(例如,成功的异步操作导致导航)。

useNavigate hook 返回一个 navigate 函数,可以调用该函数以命令式导航。 这是从副作用(例如,成功的异步操作)导航到路由的好方法。 这是一个例子

tsx
function Component() {
  const navigate = useNavigate({ from: '/posts/$postId' })

  const handleSubmit = async (e: FrameworkFormEvent) => {
    e.preventDefault()

    const response = await fetch('/posts', {
      method: 'POST',
      body: JSON.stringify({ title: 'My First Post' }),
    })

    const { id: postId } = await response.json()

    if (response.ok) {
      navigate({ to: '/posts/$postId', params: { postId } })
    }
  }
}
function Component() {
  const navigate = useNavigate({ from: '/posts/$postId' })

  const handleSubmit = async (e: FrameworkFormEvent) => {
    e.preventDefault()

    const response = await fetch('/posts', {
      method: 'POST',
      body: JSON.stringify({ title: 'My First Post' }),
    })

    const { id: postId } = await response.json()

    if (response.ok) {
      navigate({ to: '/posts/$postId', params: { postId } })
    }
  }
}

🧠 如上所示,您可以传递 from 选项来指定在 hook 调用中要从哪个路由导航。 虽然也可以在每次调用时在结果 navigate 函数中传递它,但建议在此处传递它,以减少潜在的错误,并且也不需要键入那么多!

useNavigate 返回的 navigate 函数接受 NavigateOptions 接口

偶尔,您可能会发现自己需要在组件挂载时立即导航。 您的第一反应可能是使用 useNavigate 和立即的副作用(例如 useEffect),但这没有必要。 相反,您可以渲染 Navigate 组件以达到相同的效果

tsx
function Component() {
  return <Navigate to="/posts/$postId" params={{ postId: 'my-first-post' }} />
}
function Component() {
  return <Navigate to="/posts/$postId" params={{ postId: 'my-first-post' }} />
}

Navigate 组件视为在组件挂载时立即导航到路由的一种方式。 这是处理仅客户端重定向的好方法。 它*绝对不能*替代在服务器上负责任地处理服务器感知重定向。

router.navigate

router.navigate 方法与 useNavigate 返回的 navigate 函数相同,并接受相同的 NavigateOptions 接口。 与 useNavigate hook 不同,它在您的 router 实例可用的任何地方都可用,因此是从应用程序中的任何地方(包括框架外部)以命令方式导航的好方法。

useMatchRoute<MatchRoute>

useMatchRoute hook 和 <MatchRoute> 组件是相同的,但 hook 更灵活一些。 它们都接受标准的导航 ToOptions 接口作为选项或 props,如果当前路由匹配,则返回 true/false。 它还有一个方便的 pending 选项,如果路由当前处于 pending 状态(例如,路由当前正在转换到该路由),则将返回 true。 这对于在用户导航的位置周围显示乐观 UI 非常有用

tsx
function Component() {
  return (
    <div>
      <Link to="/users">
        Users
        <MatchRoute to="/users" pending>
          <Spinner />
        </MatchRoute>
      </Link>
    </div>
  )
}
function Component() {
  return (
    <div>
      <Link to="/users">
        Users
        <MatchRoute to="/users" pending>
          <Spinner />
        </MatchRoute>
      </Link>
    </div>
  )
}

组件版本 <MatchRoute> 也可以与函数一起用作 children,以便在路由匹配时渲染某些内容

tsx
function Component() {
  return (
    <div>
      <Link to="/users">
        Users
        <MatchRoute to="/users" pending>
          {(match) => {
            return <Spinner show={match} />
          }}
        </MatchRoute>
      </Link>
    </div>
  )
}
function Component() {
  return (
    <div>
      <Link to="/users">
        Users
        <MatchRoute to="/users" pending>
          {(match) => {
            return <Spinner show={match} />
          }}
        </MatchRoute>
      </Link>
    </div>
  )
}

hook 版本 useMatchRoute 返回一个可以以编程方式调用的函数,以检查路由是否匹配

tsx
function Component() {
  const matchRoute = useMatchRoute()

  useEffect(() => {
    if (matchRoute({ to: '/users', pending: true })) {
      console.info('The /users route is matched and pending')
    }
  })

  return (
    <div>
      <Link to="/users">Users</Link>
    </div>
  )
}
function Component() {
  const matchRoute = useMatchRoute()

  useEffect(() => {
    if (matchRoute({ to: '/users', pending: true })) {
      console.info('The /users route is matched and pending')
    }
  })

  return (
    <div>
      <Link to="/users">Users</Link>
    </div>
  )
}

呼! 导航内容真多! 也就是说,希望您现在对在应用程序中导航感到非常满意。 让我们继续前进!

订阅 Bytes

您每周的 JavaScript 新闻。 每周一免费发送给超过 100,000 名开发人员。

Bytes

无垃圾邮件。 随时取消订阅。