返回博客

React Native Storybook (6.5)

性能改进,支持组件 Story 格式 (CSF)、Controls 和 Args。此外,还采用新的配置文件格式以与 Storybook 核心保持一致。

loading
Daniel Williams
@Danny_H_W
最后更新

React Native Storybook 是 Storybook 的一个专门版本,专注于为使用 React Native 构建的组件创建和组织 stories,而不是针对 HTML 和 CSS。与核心 Storybook 不同,React Native Storybook 在原生模拟器或物理移动设备上运行 stories,而不是在浏览器中。随着时间的推移,这种分歧导致 React Native Storybook 落后于浏览器版本的更新。

我很高兴地宣布 React Native Storybook 的新版本,现已兼容 Storybook 6.5.14 及更高版本。这个迭代简化了代码库,集成了更多的 Storybook 核心包,并提供了改进的开发者体验。

  • 📝 支持组件 Story 格式 (CSF)
  • 🎛️ 支持 Controls 和 Args(包括实验性的自动生成 Controls)
  • 📜 与核心格式对齐的配置(main.jspreview.js 文件)
  • ⚡ 性能改进
  • 🎨 设备端 UI 改进

为什么选择 6.5 版本?

为了让 React Native Storybook 与 Storybook 6.5 配合使用,Storybook 本身需要进行一些更改。因此,React Native Storybook 仅兼容 Storybook 6.5.14 及更高版本。这种权衡将使得 React Native Storybook 更容易与未来的 Storybook 版本集成,包括 Storybook 7.0

这个版本是多年来许多周末和深夜努力的结果。很高兴终于能和大家分享它。我要感谢社区中所有人的耐心等待,以及帮助实现这一目标的贡献者们。此外,我还要感谢许多 Storybook 维护者,他们与我结对合作,共同攻克了更新中最复杂的部分。

让我们深入了解更新!

Storybook running on an iPhone emulator and the user is navigating through the various stories

组件 Story 格式 (CSF) 支持

CSF 是 Storybook 更简单、更强大的语法,它使得 stories 更易于阅读、编写和维护。它基于 ES6 模块,使用命名导出定义 stories,使用默认导出定义元数据。React Native Storybook 现在支持 CSF。

使用 CSF,stories 以纯 JavaScript 对象编写。组件 props 使用 “Args” 指定,这是 Storybook 用于为 props 和 children 设置默认值的机制。

我们提供了一个 codemod 来简化此迁移(请参阅下面的迁移指南)。

import Button from './Button';

// The default export has metadata for your component story
export default {
   title: "Button"
   component: Button
};

// An individual story with some default props
export const Base = {
  args: {
    // default value for the 'text' property of this component
    text: "Hello World"
  }
};
User edits args for the Basic story and Storybook refreshes the UI accordingly

使用 Controls 通过图形化 UI 操纵 props

Controls 允许您无需编写代码即可与组件的 args 进行交互。Storybook 会根据组件的 PropTypes 和 TypeScript 类型自动生成 Controls。就像旧的 Knobs 插件一样,您可以使用插件面板实时编辑参数。

User manipulating the story args via the Controls panel within the Storybook running on the emulator

默认情况下,Storybook 根据 arg 的类型选择输入控件(如文本、单选、选择和范围)。您可以通过配置 argTypes 来为每个 arg 选择要使用的控件类型。请查阅 Controls 文档了解更多信息。

import Button from "./Button";

// The default export has metadata for your component story
export default {
  title: "Button",
  component: Button,

  // You can be more specfic about the type you want by using argTypes
  argTypes: {
    variant: {
      options: ["primary", "secondary"],
      control: { type: "radio" },
    },
  },
};

// An individual story with some default props
export const Primary = {
  args: {
    // default value for the 'text' property of this component
    text: "Hello World",
    variant: "primary",
  },
};

与 Storybook 核心对齐的配置格式

自 React Native 版本分歧以来,Storybook 核心最大的变化之一是切换到使用 main.jspreview.js 文件实现的更具声明性的配置格式。为了与 Storybook 核心对齐,React Native Storybook 现在也使用这种格式。

main.js 文件中,在 stories 字段中提供一个 glob 模式,并列出插件。然后 Storybook 会处理其余部分,生成一个名为 storybook.requires.js 的文件。preview.js 文件用于定义全局装饰器和参数。

更多关于语义的内容请参阅下面的升级指南。继续阅读以查看一些示例。

开始使用

如果您正在启动一个新项目,请在 React Native 项目中运行此命令以自动生成所需的配置。

npx sb@next init --type react_native 

如果您愿意,也可以使用以下模板之一。

# Expo
npx create-expo-app --template expo-template-storybook AwesomeStorybook

# React Native CLI
npx react-native init MyApp --template react-native-template-storybook

如果您是 React Native Storybook 的新手,请查看我们的实践教程以学习所有基础知识:https://storybook.org.cn/tutorials/intro-to-storybook/react-native/en/get-started/

如何升级

步骤 1:更新您的 index 文件

从您的 index.js 文件中移除 configure 调用、story 导入和 addon 导入,并将文件简化为此。最重要的是导入 storybook.requires 文件。

// .storybook/index.js
import { getStorybookUI } from '@storybook/react-native';
import './storybook.requires';

const StorybookUIRoot = getStorybookUI({
  // options go here
});

export default StorybookUI

此外,如果您的 Storybook 文件夹名为 storybook,您应将其更改为 .storybook

步骤 2:添加新的配置文件

在您的 .storybook 文件夹中,添加 main.jspreview.js 文件。

在您的 main.js 文件的 stories 字段中,根据您的项目设置更新 glob 模式。

在 addons 字段中,列出您要使用的插件。这些插件必须兼容 React Native Storybook。为 React Native 构建的插件通常以 addon-ondevice 为前缀。

// .storybook/main.js
module.exports = {
  stories: [
    '../components/**/*.stories.?(ts|tsx|js|jsx)',
  ],
  addons: [
    '@storybook/addon-ondevice-controls',
    '@storybook/addon-ondevice-actions',
    '@storybook/addon-ondevice-backgrounds',
  ],
};

将您拥有的所有全局装饰器和参数移至 preview.js。如果您没有任何全局装饰器和参数,只需分别为 decorators 导出一个空数组,为 parameters 导出一个空对象。

// .storybook/preview.js
import { View } from 'react-native';

export const decorators = [
  // Using a decorator to apply padding for every story
  (StoryFn) => (
    <View style={{flex:1, padding:8}}>
      <StoryFn />
    </View>
  ),
];

export const parameters = {
  my_param: 'anything',
};

步骤 3:将您的 stories 转换为 CSF

虽然 storiesOf 仍然可用,但它已被弃用,我们建议您将 stories 转换为 CSF。为了方便起见,我们提供了一个 codemod,它应该会自动将您的文件迁移到 CSF(请确保更新 glob 模式以匹配您的文件)。

npx storybook@next migrate storiesof-to-csf --glob="src/**/*.stories.js"

让我们看一个例子。我们将使用这个 Button.stories.js 文件

// Button.stories.js

// Before
storiesOf('Button', module)
  .addParameters({ myParam: "anything" })
  .addDecorator((Story)=> <Wrapper>{Story}</Wrapper>)
  .add('primary', () => <Button primary label="Button" />)
  .add('secondary', () => <Button label="Button" />);

codemod 会将其转换为 CSF,如下所示

// Button.stories.js (CSF1)
export default {
  title: 'Button',
  decorators: [(Story) => <Wrapper>{Story}</Wrapper>],
  parameters: {
    myParam: 'anything',
  },
};

export const Primary = () => <Button primary label="Button" />;
Primary.story = {
  name: 'primary',
};

export const Secondary = () => <Button label="Button" />;
Secondary.story = {
  name: 'secondary',
};

CSF 被设计为向后兼容,这使得 Storybook 团队能够持续改进。最新的 story 格式 CSF3 包含了一些人体工程学方面的改进。请参阅发布公告,了解所有功能和优势的完整列表。

最后,我们可以手动将文件更新为 CSF3 格式,如下所示


// Button.stories.js (CSF3)
export default {
  title: 'Button',
  decorators: [(Story) => <Wrapper>{Story}</Wrapper>],
  parameters: {
    myParam: 'anything',
  },
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
};

export const Secondary = {
  args: {
    label: 'Button',
  },
};

注意,如果您正在使用 Knobs 插件,请考虑迁移到 Controls

可选:服务器配置

服务器是一个名为 @storybook/react-native-server 的包。它是一个可选的配套应用程序,允许您通过 Web UI 控制设备上的 React Native Storybook UI。

在此版本中,服务器的配置略有变化。要配置服务器,您需要添加一个 .storybook_server 文件夹,其中包含一个 main.js 文件。在此文件中,您应该添加与 .storybook/main.js 文件中相同的 stories glob 模式。

module.exports = {
  stories: [
    '../components/**/*.stories.?(ts|tsx|js|jsx)',
  ],
  env: () => ({}),
  addons: ['@storybook/addon-essentials'],
};

然后,在 package.json 中,您需要添加一个新的脚本

"start-server": "react-native-storybook-server"

有关此服务器设置的更多信息,请阅读这篇博文

迁移问题?
有关此升级的更多详细信息,请参阅迁移指南。如果您遇到任何困难,可以在 GitHub 上提出 issue 或访问 Storybook Discord

下一步是什么?

React Native Storybook 6.5 带来了一些重大改进,但我们尚未完成。以下是您可以对 React Native Storybook 抱有的期望。

稳定 6.5 版本: 这是我们目前的首要任务。为了帮助我们实现这一目标,请在 React Native Storybook GitHub 上向我们报告任何 bug 并分享您的反馈

支持 Storybook 7.0: 随着 6.5 版本的发布,与 Storybook 7.0 版本兼容的基础工作已经基本完成。6.5 版本稳定后,将开始进行这方面的工作。

改进

未来更新有许多可能的方向,以下是我的一些改进想法。

我们还可以做很多其他事情,我们很想听听您关于下一步应该关注哪些方面的想法。

总结

React Native Storybook 由我,Daniel Williams 维护。这次更新为 React Native Storybook 带来了许多改进,并缩小了与最新 Storybook 版本之间的差距。

仍有很多地方可以改进,版本 7 肯定在我的计划中。如果您对这个项目感兴趣并想提供帮助,请联系我,我很乐意帮助您入门。此外,您可以访问 GitHub 仓库来创建 issue、提交 pull request 和发起讨论。

您可以在 Twitter (@Danny_H_W) 或 Github (dannyhw) 上找到我。如果您想支持我的工作,请考虑通过 GitHub Sponsors 赞助我。感谢您的阅读,期待您的反馈。

加入 Storybook 邮件列表

获取最新新闻、更新和版本

7,180开发者,并且还在增加

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发者在生产中使用的工具。远程优先。

查看职位

热门文章

Storybook 7.0

下一代组件开发与测试
loading
Michael Shilman

社区示例展示 #5

所有令人兴奋的近期更新回顾。此外,还有来自社区的令人惊叹的新学习资源!
loading
Joe Vaughan

Styling Addon:在 Storybook 中配置样式和主题

使用 Styling Addon 配置您的样式工具,并为您的 UI 组件提供主题。
loading
Shaun Evening
加入社区
7,180开发者,并且还在增加
为什么为什么选择 Storybook组件驱动 UI
文档指南教程更新日志遥测
社区插件参与贡献博客
示例展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI