返回博客

Storybook for React Native (6.5)

性能改进、支持组件故事格式、Controls 和 Args。此外,还新增了配置文件的格式,以与 Storybook 核心保持一致。

loading
Daniel Williams
@Danny_H_W
最后更新

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

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

  • 📝 组件故事格式支持
  • 🎛️ 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

组件故事格式 (CSF) 支持

CSF 是 Storybook 中一种更简单、更强大的语法,可以更轻松地读取、编写和维护故事。它基于 ES6 模块,使用命名导出定义故事,并使用默认导出定义元数据。React Native Storybook 现在支持 CSF。

使用 CSF,故事被写成纯 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 addon 类似,您可以使用插件面板实时编辑参数。

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/

如何升级

第一步:更新您的 index 文件

从您的 index.js 文件中移除 configure 调用、故事导入和插件导入,并将文件简化为这样。最重要的是导入 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

第二步:添加新的配置文件

在您的 .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。如果您没有任何,只需为装饰器导出一个空数组,为参数导出一个空对象。

// .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',
};

第三步:将您的故事转换为 CSF

虽然 storiesOf 仍然可用,但它现在已弃用,我们建议您将故事转换为 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 团队能够进行持续改进。最新的故事格式 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 上提出问题或访问 Storybook Discord

下一步是什么?

React Native Storybook 6.5 带来了一些重大改进,但我们并未止步。以下是您对 React Native Storybook 的期待。

稳定 6.5 版本: 这是我们目前的头等大事。为了帮助我们实现这一目标,请在 React Native Storybook GitHub 上报告任何错误并分享您的反馈

支持 Storybook 7.0: 随着 6.5 版本的发布,为与 Storybook 7 版本兼容奠定了坚实的基础。在 6.5 版本稳定后,将开始进行相关工作。

改进

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

  • 支持故事分类,以在故事列表侧边栏中进行更多组织
  • 使用 metro 的实验性 require.context 来简化故事导入
  • 更好的测试支持,包括可能支持使用 play 函数的 交互测试
  • @storybook/addon-react-native-web 更好的集成

还有很多工作可以做,我们很乐意听取您关于下一步重点的看法。

最后的话

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

仍有许多可以改进的地方,7.0 版本绝对在我考虑范围内。如果您对这个项目感兴趣并想提供帮助,请联系我,我很乐意协助您开始。此外,您可以访问 GitHub 仓库来创建 issues、打开 pull requests 和发起讨论。

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

加入 Storybook 邮件列表

获取最新消息、更新和发布信息

7,468开发者及更多

我们正在招聘!

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

查看职位

热门帖子

Storybook 7.0

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

社区案例展示 #5

近期所有令人兴奋的更新回顾。此外,社区带来了精彩的新学习资源!
loading
Joe Vaughan

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

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

特别感谢 Netlify CircleCI