ReactのUI開発を促進するstorybookを触ってみた
storybookの超基本的な使い方について紹介できればと思います。
今回はコマンド一つでreactの環境を構築できるお馴染みのcreate-reacta-app
を使っていこうと思います。
インストールしていない方は事前にしておいてください。
環境構築
ではまずは以下のコマンドを実行してください。
create-react-app storybook_paractice
プロジェクトフォルダに移動します。
cd storybook_paractice
storybookに必要なパッケージをインストールします。
yarn add @storybook/cli
package.jsonの中身はこのようになっています。
{ "name": "storybook-sample", "version": "0.1.0", "private": true, "dependencies": { "react": "^16.4.1", "react-dom": "^16.4.1", "react-scripts": "1.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "storybook": "start-storybook -p 9009 -s public", "build-storybook": "build-storybook -s public" }, "devDependencies": { "@storybook/react": "^3.4.8", "@storybook/addon-actions": "^3.4.8", "@storybook/addon-links": "^3.4.8", "@storybook/addons": "^3.4.8", "babel-core": "^6.26.3", "babel-runtime": "^6.26.0" } }
その後プロジェクトフォルダの直下で以下のコマンドを実行します。
getstorybook
このコマンドを実行するとstories
というフォルダができていると思います。
src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg ├── registerServiceWorker.js └── stories └── index.js
package.json
のscriptの部分にも記述が追加されています。
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "storybook": "start-storybook -p 9009 -s public", // 追加されている部分 "build-storybook": "build-storybook -s public" // 追加されている部分 },
では早速ローカルサーバーを起動してstorybookの画面をみてみましょう。
yarn storybook
このような画面が表示されると思います。
stories/index.js
にコンポーネントの設定をしていきます。
import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; import { Button, Welcome } from '@storybook/react/demo'; storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />); storiesOf('Button', module) .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>) .add('with some emoji', () => ( <Button onClick={action('clicked')}> <span role="img" aria-label="so cool"> 😀 😎 👍 💯 </span> </Button> ));
storiseOf()
関数の第一引数にタイトル(上のブラウザのサイドバーにあるWelcomeやButton)を、add
関数でサブメニューのような階層を作ることができます。
ストーリーを構成するコンポーネントの配置場所は任意で良いです。
またストーリーを追加するごとにページが増えます。
コンポーネントの作成
実際にコンポーネントを作成してみましょう。
まずLabelコンポーネントを作成します。今回はstyled-componetsを使うのでインストールをしましょう。
yarn add styled-components
その後、Label.jsファイルを作成します。
import React, { Component } from 'react'; import styled from 'styled-components'; class Label extends Component { render(props){ return( <LabelCom {...this.props}>Hello, storybook!</LabelCom> ) } } const LabelCom = styled.div` color: #fff; width: 200px; margin: 0 auto; padding: 10px; text-align:center; background: ${(props) => { return props.type === "alert" ? "red" : "green" }}; `; export default Label;
受け取るprops
によって背景色を変更しているだけです。
その後、stories/index.js
を編集します。
import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; import { Button, Welcome } from '@storybook/react/demo'; import Label from '../Label'; // 追加 storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />); storiesOf('Button', module) .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>) .add('with some emoji', () => ( <Button onClick={action('clicked')}> <span role="img" aria-label="so cool"> 😀 😎 👍 💯 </span> </Button> )); storiesOf('Label', module) .add('default', () => <Label type="" />) .add('alert', () => <Label type="alert" />)
props
に文字列alertを渡した時と、何も渡さない時でストーリーを分けました。
またstorybookのプレビュー画面に独自のスタイルやスクリプトを読み込ませたいときは.storybook
以下にpreview-head.html
を作成します。
例えばフォント読み込んだり、bodyにスタイルを付与しています。
<link href="https://fonts.googleapis.com/earlyaccess/roundedmplus1c.css" rel="stylesheet" /> <style> body { height: 100vh; display: flex; align-items: center; justify-content: center; } </style>
こちら公式サイトで説明されています。
https://storybook.js.org/configurations/add-custom-head-tags/
実際に画面を見るとdefault用とalert用のストーリーが確認できると思います。
アドオンの紹介
次にstorybookにはアドオン(拡張機能)があります。その中から一つinfoというものを今回は紹介します。
必要なモジュールをインストールします。
yarn add @storybook/addon-info
以下のコードを追加します。
stories/index.js
でwidthInfo
、Appコンポーネントをインポートします。(省略していますがAppコンポーネントではpropsでtextを渡すようにしています。)
import { withInfo } from '@storybook/addon-info'; import App from '../App'; storiesOf('App', module) .add('info of App', withInfo(` マークダウン形式で記述することができます。 ### タイトル ~~~js <Button>Click Here</Button> ~~~ `)(() => <App text="hello from storybook"/> ) )
widthInfoメソッドの中でマークダウンを記述することができます。 infoという拡張機能は文字の通りコンポーネントの情報について記述することに特化したものになります。
ブラウザでみるとこのようになります。
まとめ
ButtonやSideBarなどパーツごとに分けるのか、それともページごとにコンポーネントを分けるのかなど、どのようなカテゴリー分けが一般的にはあるのか気になりました。コンポーネントがどのような役割をもっているかをこのようにガイドラインのような形で確認することができるので大規模な開発では積極的につかっていきたいです。またデザイナーがコンポーネントを記述できる環境であれば、デザイナーに任せてしまうことでエンジニアがより開発の方に集中できるようになるのではないかと思いました。