尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Storybook for TanStack React 实战:用 `path` 与 `query` 精确控制 Story 的 URL 哈希与查询参数

Storybook for TanStack React 实战:用 `path` 与 `query` 精确控制 Story 的 URL 哈希与查询参数 Storybook for TanStack React 实战用path与query精确控制 Story 的 URL 哈希与查询参数【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybookStorybook for TanStack React 是 Storybook 官方为 TanStack Router / TanStack Start 应用提供的框架集成它在内存中为每个 story 启动一个 router让依赖路由状态的组件无需启动完整应用即可独立渲染。本文聚焦该框架的parameters.tanstack.router中path与query两个参数讲解如何为单个 story 精确设置 URL 片段hash如#section-name与查询字符串search params如?tabdetailspage2并深入源码说明其底层实现。读完本文你将能够在自己的 TanStack React story 中自由构造任意初始 URL 状态用于锚点滚动、列表筛选、分页等场景的组件开发与测试。背景story 内的内存路由根据框架文档 docs/get-started/frameworks/tanstack-react.mdxstorybook/tanstack-react基于storybook/react-vite构建会自动把每个 story 包裹进一个内存路由memory-backed TanStack Router中。这意味着不需要启动完整的应用外壳story 内就有一个可用的 router context可以为每个 story 单独设置初始路径、路由参数和查询字符串tanstack/react-router的导入会被自动重定向到 Storybook 兼容的 mock 层useNavigate()、useSearch()、useParams()等 hooks 在 story 中照常可用导航动作会被记录为 Storybook spy。path与query正是在这个内存路由上工作的两个参数它们共同决定 story 的初始 URL。框架文档在 Defining search params and URL fragments 一节中明确说明用query设置 search params如?tabdetailspage2用path设置 URL 片段如#section-name。核心用法为 story 设置 hash 与 search params关联文档 docs/_snippets/tanstack-react-query-and-path.md 提供了完整的可运行示例。下面按 Storybook 的两种写作范式分别展示。CSF 3 写法以Page.stories.ts为例meta 中通过parameters.tanstack.router.route指定要渲染的 TanStack Route 对象story 级再通过path/query覆盖初始 URL 状态import type { Meta, StoryObj } from storybook/tanstack-react; import { Route } from ./Page; const meta { parameters: { tanstack: { router: { route: Route, }, }, }, } satisfies Metatypeof Route; export default meta; type Story StoryObjtypeof meta; export const WithHash: Story { parameters: { tanstack: { // Provide the URL fragment (hash) for the route router: { path: /#section-name }, }, }, }; export const WithSearch: Story { parameters: { tanstack: { // Provide the query string for the route router: { query: { tab: details, page: 2 } }, }, }, };要点route: Route放在 meta 级表示该组件组的所有 story 都渲染这个路由的组件WithHash通过path: /#section-name让内存路由的初始 URL 携带 hash 片段适合验证进入页面后自动滚动/定位到某个锚点这类逻辑WithSearch通过query: { tab: details, page: 2 }让初始 URL 携带查询参数适合验证列表页读取useSearch()并按条件渲染的场景两者是各自 story 独立的互不影响。CSF Next 写法实验性CSF Next 工厂函数式写法中使用preview.meta()与meta.story()组织同样的参数语义与 CSF 3 完全一致import preview from ../.storybook/preview; import { Route } from ./Page; const meta preview.meta({ parameters: { tanstack: { router: { route: Route, }, }, }, }); export const WithHash meta.story({ parameters: { tanstack: { // Provide the URL fragment (hash) for the route router: { path: /#section-name }, }, }, }); export const WithSearch meta.story({ parameters: { tanstack: { // Provide the query string for the route router: { query: { tab: details, page: 2 } }, }, }, });参数语义与类型约束这两个参数在框架的类型定义 code/frameworks/tanstack-react/src/routing/types.ts 的RouterParameters接口中有明确声明path?: Path设置 story 路由的初始 URL 路径。在 route tree 模式下类型会被约束为应用中已注册的路径联合如/ | /admin/users | /$libraryId/$version在 app route 模式下可以是任意字符串因为用户可能传入不在注册树中的自定义route。query?: PartialStoryRouteSearchTRoute向初始 URL 追加 search params。当传入的route是文件路由File Route时类型会进一步约束为该路由声明的allSearch类型从而获得 search 字段的编译期检查非文件路由场景则回退为Recordstring, unknown。params?: ResolveParamsPath用于把/$id这类动态段插值进路径与path配合完成带参数的路由地址构造详见 框架文档 Routing 一节。从类型设计可以看出框架希望你在指定route的前提下使用query与path这样既能享受类型安全又能让内存路由的状态与真实路由定义保持一致。源码级原理内存路由如何消费 path 与 querypath与query的消费发生在渲染 decorator 中见 code/frameworks/tanstack-react/src/routing/decorator.tsx 的初始路径解析逻辑L85-L114const routerParameters: RouterParameters context.parameters.tanstack?.router ?? {}; // ... const inferredPath routerParameters?.path || leaf.fullPath || (leaf.id ? normalizeFileRoutePath(leaf.id) : undefined) || mountPathFor(leaf); // Interpolate params into the path and append query/search params. let resolvedPath interpolatePath({ path: inferredPath, params: routerParameters?.params ?? {}, }).interpolatedPath; const search routerParameters?.query ? defaultStringifySearch(routerParameters.query) : ; if (search) { resolvedPath search; } const history createMemoryHistory({ initialEntries: [resolvedPath], }); history.replace(resolvedPath); return createRouter({ // ... });对应源码可以总结出完整的路径解析优先级与拼接规则路径优先级routerParameters.path显式指定时优先使用未指定时依次回退到叶子路由的fullPath、由路由 ID 归一化得到的文件路由路径normalizeFileRoutePath实现在 code/frameworks/tanstack-react/src/routing/path-utils.ts负责剥离(group)路由组、_layout布局段与首尾下划线等文件路由命名噪音、以及沿父链推导的挂载路径mountPathFor。参数插值interpolatePath会把params对象如{ id: 42 }插值进/$id这样的动态段得到最终路径。search 拼接query对象经defaultStringifySearch序列化为 URL search string如?tabdetailspage2并直接拼接在路径之后。由于path中可以携带#hash而 search 拼接在路径末尾最终形成path ?query的完整 URL。内存历史拼接结果作为initialEntries传给createMemoryHistory并立即history.replace一次随后createRouter使用这份内存历史创建 story 专属 router。这就是为什么 story 中useSearch()、useParams()、useRouterState()能读到与真实 URL 一致的状态。另外当 story 通过route参数传入 Route 对象时code/frameworks/tanstack-react/src/routing/loader.ts 的routeComponentLoader会从路由选项中提取其 React 组件作为 story 渲染组件并保留该 Route 以提供类型化的 router 配置——这也是query能获得该路由allSearch类型约束的前提。组合实践path query params 的完整初始状态框架文档 Defining search params and URL fragments 说明query与path只是parameters.tanstack.router提供的多个属性之一它们可以和其他属性组合出任意初始 URL。参照 docs/_snippets/tanstack-react-route-story.md 的示例一个同时设置动态参数、查询参数、并 stub loader 的 story 形如import type { Meta, StoryObj } from storybook/tanstack-react; import { Route } from ./Page; const meta { parameters: { layout: fullscreen, tanstack: { router: { route: Route, // Supply the Route here // Rest of these properties are type-safe params: { id: 42 }, query: { tab: details }, }, }, }, } satisfies Metatypeof Route; export default meta; type Story StoryObjtypeof meta; export const Default: Story {}; export const WithCustomLoader: Story { parameters: { tanstack: { router: { route: Route, // Supply the Route here // Rest of these properties are type-safe params: { id: 42 }, routeOverrides: { /items/$id: { loader: async () ({ item: { id: 42, name: Loaded inside Storybook }, }), }, }, }, }, }, };在此基础上叠加本文的path与query即可得到完整形态params负责动态段、query负责 search params、path负责路径与 hashrouteOverrides负责在不改动原路由对象的前提下替换loader/beforeLoad/validateSearch/loaderDeps/context。它们共同构成一个story 级路由状态工厂让同一个组件在不同 story 中呈现完全不同的 URL 语境。典型场景与注意事项锚点定位验证path: /#section-name可用于测试进入页面后根据 hash 滚动到指定区块的行为无需真实浏览器导航。筛选与分页态query: { tab: details, page: 2 }可让列表页 story 直接进入已选中 details 标签、第二页的状态配合useSearch()渲染分支进行快照与交互测试。search 校验当route是带validateSearch的文件路由时query的键会被类型约束到该路由声明的 search schema如果路由对 search 有校验逻辑确保 story 中提供的query能通过校验否则内存路由初始加载可能失败。与 route tree 模式配合当route是接入应用 route tree 的文件路由时Storybook 会自动带上父级布局路由此时用path导航到具体路由、用routeOverridesstub 祖先路由的 guards / loaders即可让嵌套路由独立渲染见 框架文档 Rendering nested routes。类型回退如果传入的route不在注册树中path与query的类型会放宽为任意字符串 /Recordstring, unknown此时需要自行保证参数与路由语义一致。小结path与query是storybook/tanstack-react框架parameters.tanstack.router命名空间下控制 story 初始 URL 的两个核心参数path设置路径与 hash 片段query追加 search params。它们在 decorator 中被解析、插值、序列化后作为createMemoryHistory的初始条目驱动每个 story 独立的内存路由实例配合route、params、routeOverrides开发者可以为任意路由依赖组件构造精确可控的 URL 语境从而在不启动完整应用的情况下完成组件开发、文档化与测试。相关示例代码可继续查阅 docs/_snippets/tanstack-react-query-and-path.md 与框架主文档 docs/get-started/frameworks/tanstack-react.mdx底层实现可参考 code/frameworks/tanstack-react/src/routing/ 目录下的源码。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表