TanStack Router 包含多项优化,以确保您的组件仅在必要时重新渲染。这些优化包括:
TanStack Router 使用一种名为“结构共享”的技术,以在重新渲染之间尽可能多地保留引用,这对于存储在 URL 中的状态(例如查询参数)特别有用。
例如,考虑一个带有两个查询参数(foo 和 bar)的 details 路由,如下所示访问:
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 属性的部分订阅。
// 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 状态执行各种计算,从而允许您返回不同类型的值,例如对象。例如:
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 中更改。
要为细粒度选择器启用结构共享,您有两种选择:
const router = createRouter({
routeTree,
defaultStructuralSharing: true,
})
const router = createRouter({
routeTree,
defaultStructuralSharing: true,
})
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 将引发错误:
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 来防止此错误。
您每周的 JavaScript 新闻。每周一免费发送给超过 10 万名开发者。