框架
版本

渲染优化

TanStack Router 包含多项优化,以确保您的组件仅在必要时重新渲染。这些优化包括:

结构共享

TanStack Router 使用一种名为“结构共享”的技术,以在重新渲染之间尽可能多地保留引用,这对于存储在 URL 中的状态(例如查询参数)特别有用。

例如,考虑一个带有两个查询参数(foo 和 bar)的 details 路由,如下所示访问:

tsx
const search = Route.useSearch()
const search = Route.useSearch()

当仅通过从 /details?foo=f1&bar=b1 导航到 /details?foo=f1&bar=b2 更改 bar 时,search.foo 将保持引用稳定,并且仅 search.bar 将被替换。

细粒度选择器

您可以使用各种 hook(例如 useRouterState、useSearch 等)访问和订阅 router 状态。如果您只想在 router 状态的特定子集(例如查询参数的子集)更改时重新渲染特定组件,则可以使用带有 select 属性的部分订阅。

tsx
// component won't re-render when `bar` changes
const foo = Route.useSearch({ select: ({ foo }) => foo })
// component won't re-render when `bar` changes
const foo = Route.useSearch({ select: ({ foo }) => foo })

带有细粒度选择器的结构共享

select 函数可以对 router 状态执行各种计算,从而允许您返回不同类型的值,例如对象。例如:

tsx
const result = Route.useSearch({
  select: (search) => {
    return {
      foo: search.foo,
      hello: `hello ${search.foo}`,
    }
  },
})
const result = Route.useSearch({
  select: (search) => {
    return {
      foo: search.foo,
      hello: `hello ${search.foo}`,
    }
  },
})

虽然这可行,但这将导致您的组件每次都重新渲染,因为 select 现在每次调用时都会返回一个新对象。

您可以通过使用上面描述的“结构共享”来避免此重新渲染问题。默认情况下,结构共享已关闭以保持向后兼容性,但这可能会在 v2 中更改。

要为细粒度选择器启用结构共享,您有两种选择:

在 router 选项中默认启用

tsx
const router = createRouter({
  routeTree,
  defaultStructuralSharing: true,
})
const router = createRouter({
  routeTree,
  defaultStructuralSharing: true,
})

按照此处所示,在每个 hook 用法中启用

tsx
const result = Route.useSearch({
  select: (search) => {
    return {
      foo: search.foo,
      hello: `hello ${search.foo}`,
    }
  },
  structuralSharing: true,
})
const result = Route.useSearch({
  select: (search) => {
    return {
      foo: search.foo,
      hello: `hello ${search.foo}`,
    }
  },
  structuralSharing: true,
})

重要提示

结构共享仅适用于 JSON 兼容的数据。这意味着如果启用了结构共享,则不能使用 select 返回类实例等项。

根据 TanStack Router 的类型安全设计,如果您尝试以下操作,TypeScript 将引发错误:

tsx
const result = Route.useSearch({
  select: (search) => {
    return {
      date: new Date(),
    }
  },
  structuralSharing: true,
})
const result = Route.useSearch({
  select: (search) => {
    return {
      date: new Date(),
    }
  },
  structuralSharing: true,
})

如果在 router 选项中默认启用了结构共享,则可以通过设置 structuralSharing: false 来防止此错误。

订阅 Bytes

您每周的 JavaScript 新闻。每周一免费发送给超过 10 万名开发者。

Bytes

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