文档
Storybook 文档

模拟 providers

组件可以从 context providers 接收数据或配置。例如,一个 styled component 可能会从 ThemeProvider 访问其主题,或者 Redux 使用 React context 来提供组件访问应用数据。要模拟 provider,你可以将你的组件包裹在一个 decorator 中,该 decorator 包含必要的 context。

.storybook/preview.tsx
import React from 'react';
 
import { Preview } from '@storybook/react';
 
import { ThemeProvider } from 'styled-components';
 
const preview: Preview = {
  decorators: [
    (Story) => (
      <ThemeProvider theme="default">
        {/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it  */}
        <Story />
      </ThemeProvider>
    ),
  ],
};
 
export default preview;

注意上面的文件扩展名(.tsx.jsx)。你可能需要调整你的预览文件的扩展名以允许使用 JSX,具体取决于你的项目设置。

有关另一个示例,请参考 Storybook 入门教程的 Screens 章节,我们在其中使用模拟数据模拟了 Redux provider。

配置模拟 provider

在模拟 provider 时,可能需要配置 provider 以便为各个 story 提供不同的值。例如,你可能想要使用不同的主题或用户角色来测试组件。

一种方法是为每个 story 单独定义 decorator。但是,如果你设想一种场景,你希望为浅色和深色主题中的每个组件创建 story,这种方法很快就会变得很麻烦。

为了获得更好、重复性更低的方法,你可以使用 decorator 函数的第二个 “context” 参数 来访问 story 的 parameters 并调整提供的值。这样,你可以定义一次 provider,并为每个 story 调整其值。

例如,我们可以调整上面的 decorator 以从 parameters.theme 读取,以确定要提供的主题

.storybook/preview.tsx
import React from 'react';
 
import type { Preview } from '@storybook/react';
import { ThemeProvider } from 'styled-components';
 
// themes = { light, dark }
import * as themes from '../src/themes';
 
const preview: Preview = {
  decorators: [
    // 👇 Defining the decorator in the preview file applies it to all stories
    (Story, { parameters }) => {
      // 👇 Make it configurable by reading the theme value from parameters
      const { theme = 'light' } = parameters;
      return (
        <ThemeProvider theme={themes[theme]}>
          <Story />
        </ThemeProvider>
      );
    },
  ],
};
 
export default preview;

现在,你可以在你的 stories 中定义一个 theme 参数,以调整 decorator 提供的主题

Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  component: Button,
};
export default meta;
 
type Story = StoryObj<typeof Button>;
 
// Wrapped in light theme
export const Default: Story = {};
 
// Wrapped in dark theme
export const Dark: Story = {
  parameters: {
    theme: 'dark',
  },
};

这种强大的方法允许你以灵活且可维护的方式为组件提供任何值(主题、用户角色、模拟数据等)。