TanStack Router 把“路由将要去哪”作为数据加载入口。它比组件内 useEffect 更早,比随手 fetch 更可追踪。
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
component: PostsPage,
})
function PostsPage() {
const posts = Route.useLoaderData()
return <PostList posts={posts} />
}loaderDeps 告诉 Router:这个 loader 的结果依赖哪些 search 参数。依赖变了,缓存 key 变,loader 重新跑。
export const Route = createFileRoute('/posts')({
validateSearch: z.object({ page: z.number().catch(1), q: z.string().catch('') }),
loaderDeps: ({ search }) => ({ page: search.page, q: search.q }),
loader: ({ deps }) => fetchPosts(deps),
})loaderDeps: ({ search }) => search。如果 loader 只用 page,却把 view、panel、debug 等无关 search 也放进依赖,任何 UI 状态变化都会导致数据重载。缓存 key 不是垃圾桶,第二次提醒,说明人类真的很爱垃圾桶。export const Route = createFileRoute('/dashboard')({
beforeLoad: async ({ context }) => {
const user = await context.auth.getUser()
if (!user) throw redirect({ to: '/login' })
return { user }
},
})父 route 的 context 可以被子 route 继承,用于 auth、feature flags、queryClient、tenant 等。
TanStack Router 有 pendingComponent、errorComponent、onError/onCatch。和 Next 的 loading.tsx/error.tsx 类似,但更贴近 route option,而不是纯文件约定。
loaderDeps 应包含什么?