Storybook とは?

UI コンポーネントのカタログ 📖 みたいなやつです。
実際に見た方が雰囲気は掴めると思うので gif を貼っておきます↓

storybook

Props を渡すことでコンポーネントの複数の状態をカタログ化することもできます。
↑の例だと、 Pagination コンポーネントに対して "全体のページ数" と "現在のページ" を渡すことで状態を変化させています。
コードは以下のような感じです。

import React from "react";
import Pagenation from "components/Pagenation";

export default {
  title: "Pagenation",
  component: Pagenation,
}

export const First = () => <Pagenation totalPages={10} currentPage={1} />;
export const Middle = () => <Pagenation totalPages={10} currentPage={5} />;
export const Last = () => <Pagenation totalPages={10} currentPage={10} />;

何が嬉しいのか?

デザインチェックが簡単にできる

コンポーネントの定義と Storybook の設定さえすればすぐに見た目の確認ができます。
カタログとしての用途もあるので、どんなコンポーネントが定義されているか把握できます。
一覧化しておくことで、重複や不要になったコンポーネントの発見にも役立ちそうです。

コンポーネントの独立性を高めるよう意識させられる

コンポーネントが色々なコンテキストに依存すると、それだけ Storybook に表示しづらくなります。 Storybook 側でその依存を解決しなければならないからです。
そのため、コンポーネントの独立性を保つような書き方が自然と求められます。

スタイルに関しても同様です。
例えば上の gif だと、Footer の表示で Tags のスタイルが崩れています。
これは、スタイルがコンポーネント内で完結しておらず外部に依存してしまっているためです 😢

Snapshot テストを楽にしてくれる

Add-on を追加すれば、マークアップに変更がないことを担保してくれる Snapshot テストを楽にしてくれます。
以下を Jest のテストとして追加しておくだけで、 Storybook に追加済のコンポーネントは全て Snapshot に保存してテストされます。

import initStoryshots from '@storybook/addon-storyshots';
initStoryshots();

Jest 単体での Snapshot は、例えば以下のようにコンポーネント毎にテストを定義しなければならなかったので、それが簡略化できるのはかなり有り難いです 🎉

import React from 'react';
import renderer from 'react-test-renderer';
import Link from '../Link.react';

it('renders correctly', () => {
  const tree = renderer
    .create(<Link page="http://www.facebook.com">Facebook</Link>)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

まとめ

Storybook はフロントエンドコンポーネントを健全に保つために役立ちそうです。