React Storybook は React をコンポーネント単位でサンドボックスで開発できる開発環境です。
- Introducing React Storybook — KADIRA VOICE — Medium
- kadirahq/react-storybook: Isolate your React UI Component development from the main app
React Storybookの特徴って
実際のReact Componentをサンドボックス内で呼び出してレンダリングします。よってコンポーネントの色々な状態(0件とか新着ありとか)も少ないコードでカタログ化が可能。また、actionというAPIを使ってコンポーネントのイベントをキャッチしてログに流してくれたりもします。
状態込みのスタイルガイドって非常にメンテナンスが面倒なので、これ使えたらかなり革新的じゃないかなぁ……
-
iframe
を利用したサンドボックス内にコンポーネントを隔離します - モジュールは自動でリロードされます(関数型のステートレスなモジュールも含め)
-
Redux
やRelay
、Meteor
などを使っていても利用可能 - さまざまなタイプのCSS()に対応しています
- 早くてかっこいいUI
- プロジェクト内で動作するので、
npm
やbabel
などアプリの環境を使いまわせます - 静的ファイルのサービングも可能
-
Webpack
をカスタマイズしたりプラグインを追加したりと拡張が可能
デモを触ってみる
git clone https://github.com/kadira-samples/react-storybook-demo
npm install
npm run storybook
Redux
で実装された TODOアプリ のデモになります。
React Storybookが無事に起動できたらhttp://localhost:9001
にアクセスしてみましょう。
インストール
では、実際に自分のReactプロジェクトにインストールしてみましょう。
-
@kadira/storybook
をインストール - 必要なモジュールをインストール
-
package.json
に実行用スクリプトを追加
npm i --save-dev @kadira/storybook
npm i --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-2 react react-dom stack-source-map webpack webpack-hot-middleware
{
...
"scripts": {
"storybook": "start-storybook -p 9001"
}
...
}
使ってみる
ストーリーを作る (components/stories/story.js
)
まずはstoryを作ります。
どこに作っても良いのですが、基本的にコンポーネントと1:1で対応するものなので、components/stories/
みたいなフォルダを作って、そこに入れていくのが推奨されています。
サンプルドキュメントからボタン2種類が登録されたストーリーを作ってみましょう。
import React from 'react';
import { storiesOf, action } from '@kadira/storybook';
storiesOf('Button', module)
.add('with a text', () => (
<button>My First Button</button>
))
.add('with no text', () => (
<button></button>
));
storiesOf
で指定するのがコンポーネントですね。さらにチェインして.add()
でモジュールの状態を追加しておきます。
例えば、validateField
というコンポーネントに対して、「未入力」「not valid」「valid」の3種類を.add()
するみたいな感じです。
Storyを読み込む (.storybook/config.js
)
これで起動しようとしても.storybook/config.js
を作れと言われるので、ドキュメントを参考に作ります。
import { configure } from '@kadira/storybook';
import 'css/style.css';
function loadStories() {
require('../components/stories/button');
}
configure(loadStories, module);
loadStories()
内で先ほど作ったストーリーをインポートします。たくさんコンポーネントがある場合は並べてもいいし、フォルダまとめて登録する方法なんかもドキュメントに書いてあります。
スタイルシートを設定する場合は、import
で可能なのですが、Reactには色々なCSSの流儀があるので詳細はドキュメントを読みましょう。
起動する
npm run storybook
やっとこれで準備できました。
http://localhost:9001
にアクセスできて左側にbutton
が表示されていればOK。
イベントをキャッチする (action()
)
Storybookにはさらにコンポーネントのイベントをキャッチする機能が搭載されています。先ほどのbutton.js
を以下のように書き換えてみましょう。
import React from 'react';
import { storiesOf, action } from '@kadira/storybook';
storiesOf('Button', module)
.add('with a text', () => (
<button onClick={action('click')}>My First Button</button>
))
.add('with no text', () => (
<button></button>
));
テキスト付きボタンの方を押すと、下の"ACTION LOGGER"にログが流れたと思います。
自作のコンポーネントをストーリーに登録する
ボタンのサンプルでは自作のコンポーネントを読み込んでいませんが、普通にimport
文で読み込んで、それを使用したストーリーを.add()
すればOKです。サンプルの TODOアプリ には4つのストーリーが登録されていますが、それぞれ特徴的になっているので参考になると思います。
エンジニアとデザイナーのコミュニケーション改善に役立つんじゃない?
うまくいくかは分からないですが、以下みたいな使い方すると「あれがなかった!」「これ伝え忘れた」みたいなの防げそうな予感。
- エンジニアが必要なストーリーを書いてそれをデザイナーに渡す
- デザイナーはそれに対して(ストーリー内で)デザイン&コーディングを行う
- エンジニアがそのコードをコンポーネント化する
- それ以降はこのストーリー上でデザインの変更を行う
また、状態のパターンやどんなアクションがあるかなど、ストーリーを見ると一目瞭然なので、仕様書代わりとしても機能するんじゃないかな、と思います。
最後に「こんな風にしたらうまくいくぜ」的なマントラがドキュメント中にあったので意訳しておきます。
- コンポーネントは
props
を使ってデータを受け渡ししましょう。分割するのが楽になります- UIコンポーネント中にアプリに依存したコードは書かないようにしましょう
- ストーリーはコンポーネント近くに置きましょう。
components
フォルダの中なんかは最適ですMeteor
を使う場合はストーリーをtests
フォルダの中にするか.stories
にしないとダメです- ひとつのストーリーではひとつのコンポーネントに対するストーリーを書きましょう
- ストーリーにプレフィックスをつけるならドットがオススメ(例:
storiesOf('core.Button', module)
)- イベントハンドラのデバッグには必ず
actions()
を使いましょう