[create-react-app] Storybookを使う方法

[create-react-app] Storybookを使う方法

2023-08-29 hit count image

create-react-appで生成したTypeScriptベースのReactプロジェクトにStorybookをインストールして使う方法について説明します。

概要

今回のブログポストではcreate-react-appを使ってTypeScriptをベースにしたReactプロジェクトにStorybookをインストールして使う方法について説明します。

CRAを使ってTypeScriptベースのReactプロジェクトw生成

CRA(create-react-app)を使ってTypeScriptが適用されたReactプロジェクトでStorybookを使うため、次のコマンドを実行してTypeScriptが適用されたReactプロジェクトを生成します。

npx create-react-app storybook_example --template=typescript

Storybookのインストール

TypeScriptが適用されたReactプロジェクトでStorybookを使うためにはStorybookをインストールする必要があります。次のコマンドを実行してStorybookをインストールします。

# cd storybook_example
npm install --save-dev storybook

Storybookの初期化

Storybookを使うためにはStorybookを初期化して必要なライブラリをインストールする必要があります。次のコマンドを実行してStorybookを初期化します。

npx storybook init

そしたら次のようにESLintに必要なライブラリをインストールするかどうかを聞く画面が出ます。

. ✓
 • Adding Storybook support to your "Create React App" based project
  ✔ Getting the correct version of 12 packages
? We have detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: https://github.com/storybookjs/eslint-plugin-storybook#readme

Would you like to install it? › (Y/n)

このブログポストではyを押してESLintに必要なライブラリをインストールしました。そしたら次のように必要なライブラリがインストールされてStorybookが自動で設定されることが確認できます。

info => Serving static files from ././public at /
info => Starting manager..
info Addon-docs: using MDX2
info => Loading Webpack configuration from `node_modules/react-scripts`
info => Removing existing JavaScript and TypeScript rules.
info => Modifying Create React App rules.
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
One of your dependencies, babel-preset-react-app, is importing the
"@babel/plugin-proposal-private-property-in-object" package without
declaring it in its dependencies. This is currently working because
"@babel/plugin-proposal-private-property-in-object" is already in your
node_modules folder for unrelated reasons, but it may break at any time.

babel-preset-react-app is part of the create-react-app project, which
is not maintianed anymore. It is thus unlikely that this bug will
ever be fixed. Add "@babel/plugin-proposal-private-property-in-object" to
your devDependencies to work around this error. This will make this message
go away.

No issues found.
<i> [webpack-dev-middleware] wait until bundle finished: /runtime~main.iframe.bundle.js
<i> [webpack-dev-middleware] wait until bundle finished: /vendors-node_modules_pmmmwh_react-refresh-webpack-plugin_client_ErrorOverlayEntry_js-node_mod-e1efac.iframe.bundle.js
<i> [webpack-dev-middleware] wait until bundle finished: /main.iframe.bundle.js
No issues found.

問題なく必要なライブラリがインストールされてStorybookが自動で設定されたら次のようにStorybookのチュートリアルが実行されることが確認できます。

Storybook V7 Storybook tour

Start your 3 minute tourを押してチュートリアルを進めても良いですが、このブログポストではSkip tourを押してチュートリアルをスキップして進めました。

問題なくStorybookのインストールが完了されたらpackage.jsonファイルが次のように修正されることが確認できます。

{
   ...
   "scripts": {
    ...
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "eslintConfig": {
    "extends": [
      ...
      "plugin:storybook/recommended"
    ]
  },
  ...
  "devDependencies": {
    "@storybook/addon-essentials": "^7.3.2",
    "@storybook/addon-interactions": "^7.3.2",
    "@storybook/addon-links": "^7.3.2",
    "@storybook/addon-onboarding": "^1.0.8",
    "@storybook/blocks": "^7.3.2",
    "@storybook/preset-create-react-app": "^7.3.2",
    "@storybook/react": "^7.3.2",
    "@storybook/react-webpack5": "^7.3.2",
    "@storybook/testing-library": "^0.2.0",
    "babel-plugin-named-exports-order": "^0.0.2",
    "eslint-plugin-storybook": "^0.6.13",
    "prop-types": "^15.8.1",
    "storybook": "^7.3.2",
    "webpack": "^5.88.2"
  }
}

また、次のようにStorybookを使う方法を説明するため、サンプルコードが一緒に生成されることが確認できます。

  • ./.storybook/...: Storybookに関する設定ファイルです。
  • ./src/stories/...: Storybookのサンプルコードです。

Storybookの実行

Storybookをインストールしたら自動でStorybookの開発サーバが実行されてStorybookが自動で実行されることが確認できます。このように実行されたStorybookを終了した後、再び実行するためには次のコマンドを実行する必要があります。

npm run storybook

そしたらブラウザにhttp://localhost:6006/が自動で開いて、次のような画面を確認することができます。

Storybook screen

該当画面は./src/stories/Configure.mdxファイルが表示された画面です。

Storybookの確認

実行されたStorybookの左メニューのButton > Docsを選択すると次のような画面が確認できます。

Storybook button sample

この画面は./src/stories/Button.tsxファイルがが表示された画面です。

サンプルコードの確認

もっと詳しくサンプルコードを確認してみましょう。Buttonコンポーネント(./src/stories/Button.tsx)は次のようです。

import React from 'react';
import './button.css';

interface ButtonProps {
  primary?: boolean;
  backgroundColor?: string;
  size?: 'small' | 'medium' | 'large';
  label: string;
  onClick?: () => void;
}

export const Button = ({
  primary = false,
  size = 'medium',
  backgroundColor,
  label,
  ...props
}: ButtonProps) => {
  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
  return (
    <button
      type="button"
      className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
      style=
      {...props}
    >
      {label}
    </button>
  );
};

ButtonコンポーネントはprimarybackgroundColorなでお色んなPropsを持っていることが確認できます。次はStorybookファイル(./src/stories/Button.stories.ts)の内容を確認してみましょう。

import type { Meta, StoryObj } from '@storybook/react';

import { Button } from './Button';

const meta = {
  title: 'Example/Button',
  component: Button,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
  argTypes: {
    backgroundColor: { control: 'color' },
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

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

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

export const Large: Story = {
  args: {
    size: 'large',
    label: 'Button',
  },
};

export const Small: Story = {
  args: {
    size: 'small',
    label: 'Button',
  },
};

まず、Storybookの画面構成に必要な情報を準備します。

import type { Meta, StoryObj } from '@storybook/react';

import { Button } from './Button';

const meta = {
  title: 'Example/Button',
  component: Button,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
  argTypes: {
    backgroundColor: { control: 'color' },
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;
...

metaStorybookに表示する基本情報を設定します。metaに設定したtitleStorybookの左メニューに表示される名前で/を使ってグループを作ることができます。例題コードではExampleグループ下にButtonと言う名前が表示されることが確認できます。

Storybook meta information

metacomponentはこのStorybookに表示するコンポーネントを指定します。例題ではButtonコンポーネントを指定しました。

tags: ['autodocs']は自動でドキュメント(Document)を作成する新しい機能です。この値を設定すると上の画面のようにExample/Buttonメニュー下にDocsが自動で作成されることが確認できます。ここでStorybookファイルに書いた内容をドキュメント形式で確認できます。

このように画面構成に必要な情報を設定したら、次は実際に画面に表示されるStoryを作成します。次のようにコンポーネントのPropsを設定したり変更することでStoryを作成することができます。

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

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

export const Large: Story = {
  args: {
    size: 'large',
    label: 'Button',
  },
};

export const Small: Story = {
  args: {
    size: 'small',
    label: 'Button',
  },
};

このように作成したStoryは左メニューのDocsの下に表示されることが確認できます。

Storybook meta information

これを使うと他の開発者がどのPropsを変更するとどのように変わるかを確認することができるし、必要な状態のコンポーネントを簡単に持ってこれるようになります。

完了

今回のブログポストではcreate-react-appで作ったTypeScriptベースのReactプロジェクトにStorybookをインストールして実行する方法について見てみました。StorybookReactプロジェクトでコンポーネントを開発してテストするのにとても便利なツールです。また、Storybookを使うとReactプロジェクトでCDD(Component Driven Development)をすることができますので、皆さんも自分のプロジェクトに入れて使ってみてください。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts