框架
版本

渲染优化

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

结构共享

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

例如,考虑一个具有两个搜索参数 foobardetails 路由,访问方式如下:

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

当仅 bar 改变时(从 /details?foo=f1&bar=b1 导航到 /details?foo=f1&bar=b2),search.foo 将保持引用稳定,只有 search.bar 会被替换。

细粒度选择器

您可以使用 useRouterStateuseSearch 等各种 Hook 访问和订阅路由器状态。如果您只想在路由器状态的特定子集(例如搜索参数的子集)发生变化时才重新渲染特定组件,则可以使用带有 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 函数可以对路由器状态执行各种计算,允许您返回不同类型的值,例如对象。例如:

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 中改变。

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

在路由器选项中默认启用它

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,
})

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

我们的合作伙伴
Code Rabbit
Netlify
Neon
Clerk
Convex
Sentry
订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

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

订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

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