参加直播:美国东部时间周四上午 11 点,Storybook 9 发布及问答

Remix React Router(原名 React Router v6)

在 Story 中使用 Remix React Router。(原名 storybook-addon-react-router-v6)

在 Github 上查看

Storybook 插件 Remix React Router

Storybook npm Release npm

在 Story 中使用 Remix React Router。

react-router@7 开始,Remix 已弃用 react-router-dom 包。
如果你仍然使用此包,请使用此插件的 v3 版本。
如果你已放弃使用该包而改用 react-router,请根据你的 Storybook 版本使用 v4v5
请查看底部的兼容性表格。

最新变更

✅ 通过 storybook-addon-remix-react-router@5 支持 Storybook 9。
✅ 通过 storybook-addon-remix-react-router@4 支持 React Router v7。
✅ 通过 storybook-addon-remix-react-router@3 支持 Storybook 8。

开始使用

安装包

npm i -D storybook-addon-remix-react-router

添加到 Storybook 配置

// .storybook/main.ts

export default {
  addons: ['storybook-addon-remix-react-router'],
} satisfies StorybookConfig;

装饰组件的所有 Story

要将路由器添加到组件的所有 Story 中,只需将其添加到 decorators 数组即可。

请注意,parameters.reactRouter 是可选的,默认情况下路由器将在 / 路径下渲染组件。

import { withRouter, reactRouterParameters } from 'storybook-addon-remix-react-router';

export default {
  title: 'User Profile',
  render: () => <UserProfile />,
  decorators: [withRouter],
  parameters: {
    reactRouter: reactRouterParameters({
      location: {
        pathParams: { userId: '42' },
      },
      routing: { path: '/users/:userId' },
    }),
  },
};

装饰特定的 Story

要更改单个 Story 的配置,可以执行以下操作

import { withRouter, reactRouterParameters } from 'storybook-addon-remix-react-router';

export default {
  title: 'User Profile',
  render: () => <UserProfile />,
  decorators: [withRouter],
};

export const FromHomePage = {
  parameters: {
    reactRouter: reactRouterParameters({
      location: {
        pathParams: { userId: '42' },
        searchParams: { tab: 'activityLog' },
        state: { fromPage: 'homePage' },
      },
      routing: {
        path: '/users/:userId',
        handle: 'Profile',
      },
    }),
  },
};

全局装饰所有 Story

通过将装饰器添加到 preview.js 文件中,将项目的所有 Story 包装在路由器内。

// .storybook/preview.js

export default {
  decorators: [withRouter],
  parameters: {
    reactRouter: reactRouterParameters({ ... }),
  }
} satisfies Preview;

位置

要指定与浏览器位置相关的任何内容,请使用 location 属性。

type LocationParameters = {
  path?: string | ((inferredPath: string, pathParams: Record<string, string>) => string | undefined);
  pathParams?: PathParams;
  searchParams?: ConstructorParameters<typeof URLSearchParams>[0];
  hash?: string;
  state?: unknown;
};

推断路径

如果未提供 location.path,浏览器路径名将使用 routing 属性中的合并 path 以及 pathParams 生成。

函数作为路径

你可以为 path 提供一个函数。
它将接收来自路由属性的合并 pathpathParams 作为参数。
如果函数返回一个 string,它将按原样使用。如果你需要,可以自行调用 react-router 中的 generatePath
如果函数返回 undefined,它将回退到默认行为,就像你没有为 location.path 提供任何值一样。

路由

你可以将 routing 设置为 createBrowserRouter 接受的任何值。
为了方便你,storybook-addon-remix-react-router 提供了一些路由助手

export const MyStory = {
  parameters: {
    reactRouter: reactRouterParameters({
      routing: reactRouterOutlet(<MyOutlet />),
    }),
  },
};

路由助手

开箱即用以下助手

reactRouterOutlet(); // Render a single outlet
reactRouterOutlets(); // Render multiple outlets
reactRouterNestedOutlets(); // Render multiple outlets nested one into another
reactRouterNestedAncestors(); // Render the story as an outlet of nested outlets

你也可以创建自己的助手并使用导出的类型 RoutingHelper 来辅助你

import { RoutingHelper } from 'storybook-addon-remix-react-router';

const myCustomHelper: RoutingHelper = () => {
  // Routing creation logic
};

RouterRoute 本质上是来自 react-router 的原生 RouteObject;并增加了一个属性 { useStoryElement?: boolean }。如果你想接受一个 JSX 并将其转换为 RouterRoute,可以使用导出的函数 castRouterRoute

使用 Story 作为路由元素

只需在路由配置对象中设置 { useStoryElement: true }

专用面板

导航事件、loader 和 action 会被记录下来,以便你更好地理解组件的生命周期。

Addon Panel

兼容性

此包旨在支持 Storybook > 7React > 16
以下是兼容性表格

插件 React Storybook React Router
5.x >= 16.8.0 9.x 7.x
4.x >= 16.8.0 8.x 7.x
3.x >= 16.8.0 8.x 6.x 1
2.x >= 16.8.0 < 19.0.0 7.x 6.x
1.x >= 16.8.0 < 19.0.0 7.x 6.x

1 实际上,如果你从 react-router-dom 而不是 react-router 导入,可以使用 react-router v7。

如果你在使用任何版本时遇到问题,请提交 issue。

贡献

欢迎贡献。

在编写任何代码之前,请先提交一个 issue,以展示你在此插件中希望看到的错误或功能用例。

许可

此包根据 Apache 2.0 许可发布。