Docs
Storybook Docs

模拟提供商

组件可以从上下文提供程序接收数据或配置。例如,样式化的组件可以从 ThemeProvider 访问其主题,或者 Redux 使用 React 上下文为组件提供对应用数据的访问。要模拟提供程序,你可以将组件封装在包含必要上下文的 decorator 中。

¥Components can receive data or configuration from context providers. For example, a styled component might access its theme from a ThemeProvider or Redux uses React context to provide components access to app data. To mock a provider, you can wrap your component in a decorator that includes the necessary 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,具体取决于你的项目设置。

¥Note the file extension above (.tsx or .jsx). You may need to adjust your preview file's extension to allow use of JSX, depending on your project's settings.

对于另一个示例,请参考 Storybook 简介教程的 屏幕 章节,其中我们使用模拟数据模拟 Redux 提供程序。

¥For another example, reference the Screens chapter of the Intro to Storybook tutorial, where we mock a Redux provider with mock data.

配置模拟提供程序

¥Configuring the mock provider

模拟提供程序时,可能需要配置提供程序以针对各个故事提供不同的值。例如,你可能希望测试具有不同主题或用户角色的组件。

¥When mocking a provider, it may be necessary to configure the provider to supply a different value for individual stories. For example, you might want to test a component with different themes or user roles.

执行此操作的一种方法是单独定义每个故事的装饰器。但是,如果你想象一个场景,你希望在浅色和深色主题中为每个组件创建故事,这种方法很快就会变得繁琐。

¥One way to do this is to define the decorator for each story individually. But if you imagine a scenario where you wish to create stories for each of your components in both light and dark themes, this approach can quickly become cumbersome.

为了以更少的重复方式更好地使用,你可以使用 装饰器函数的第二个 "context" 参数 访问故事的 parameters 并调整提供的值。这样,你可以定义一次提供程序并为每个故事调整其值。

¥For a better way, with much less repetition, you can use the decorator function's second "context" argument to access a story's parameters and adjust the provided value. This way, you can define the provider once and adjust its value for each story.

例如,我们可以调整上面的装饰器以从 parameters.theme 读取以确定提供哪个主题:

¥For example, we can adjust the decorator from above to read from parameters.theme to determine which theme to provide:

.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;

现在,你可以在故事中定义 theme 参数来调整装饰器提供的主题:

¥Now, you can define a theme parameter in your stories to adjust the theme provided by the 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',
  },
};

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

¥This powerful approach allows you to provide any value (theme, user role, mock data, etc.) to your components in a way that is both flexible and maintainable.