react + storybookを試してみた
Reactでプロジェクトを開発するため、Component単位でソースを分けるのはすごくいいです。
でもその時、ドキュメンテーションはどうやっていますか?エンジニア以外のメンバーに見せるために、コンポーネント一覧の画面を用意しないとですね。例えばそれぞれの属性とか、色々データーのヴァリエーションとか。
これは、結構、めんどくさい。でもstorybookが助けてくれるので、見てみましょう
install storybook
例えReact プロジェクトで、components/Button.js
にはこんなコードとしよう:
import React from 'react';
import PropTypes from 'prop-types';
function Button(props) {
const {children, ...other} = props;
return <button {...other}>{props.children}</button>;
}
Button.propTypes = {
size: PropTypes.oneOf(['small', 'big'])
};
export default Button;
公式ドキュメントにしたがってインストールする:
npm i --save-dev @storybook/react
package.jsonにコマンドを追加する。
{
"scripts": {
"storybook": "start-storybook -p 9001 -c .storybook"
}
}
storybookをコンフィグ
まず.storybook/config.js
を追加する:
import { configure } from '@storybook/react';
function loadStories() {
require('../stories/index.js');
}
configure(loadStories, module);
stories
にある全てのstoryを全部loadする意味。
storyを追加
strories/
の下にindex.js
を追加する
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
storiesOf('Button', module)
.add('with text', () => {
return <Button >Arunoda Susiripala</Button>
})
.add('with some emoji', () => (
<Button ><span role="img" aria-label="so cool">😀 😎 👍 💯</span></Button>
));
> npm run storybook
見ればわかるが:
- サイドバーにstory一覧がみれる
- 右側にstoryの中身を表示する
knobs
knobは引き手の意味、つまり表示内容を操作できるのね 直接コンポーネントを弄りたい場合は、プラグインを使ったらいい
npm install @storybook/addon-knobs --save-dev
.storybook/addons.js
にプラグインを入れる:
import '@storybook/addon-knobs/register';
最後にstoryの中にプラグインを使う。
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
storiesOf('Button', module)
.addDecorator(withKnobs)
.add('with text', () => {
const name = text('Name', 'Arunoda Susiripala');
return <Button onClick={action('clicked')}>{name}</Button>
})
knobs panelが追加されるのがわかりました
PropType
react componentのpropsはどう処理する?まずButtonのpropsを定義しましょう
import React from 'react';
import PropTypes from 'prop-types';
const fontSize = {
small: '12px',
big: '16px'
};
function Button(props) {
const {children, ...other} = props;
return <button {...other} style={{fontSize: fontSize[props.size]}}>{props.children}</button>;
}
Button.propTypes = {
size: PropTypes.oneOf(['large', 'big']),
color: PropTypes.string
};
export default Button;
storyにも変更を入れる
import { withKnobs, text, select } from '@storybook/addon-knobs';
storiesOf('Button', module)
.addDecorator(withKnobs)
.add('with text', () => {
const name = text('Name', 'Arunoda Susiripala');
const size = select('size', ['large', 'small']);
const color = text('color', 'green')
return <Button onClick={action('clicked')} size={size} color={color}>{name}</Button>
})
これで、size
, color
, name
は全部編集できるようになりました。
snapshot test
まず普通にunit testをやる時:
- jest enzymeを使って、unit testを書く
- jestでsnapshot testをやる
まずstorybookがない時のsnapshotのやり方をみてみましょう
npm install --save-dev jest react-test-renderer babel-preset-env babel-preset-react
packae.json
"scripts": {
"test": "jest --no-watchman",
"storybook": "start-storybook -p 9001 -c .storybook"
},
test spec, __test__/Button.test.js
を追加する
import React from 'react';
import Button from '../components/Button';
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer
.create(<Button size="large" color="green">sunderls</Button>)
.toJSON();
expect(tree).toMatchSnapshot();
});
presetをbabelrcに追加しないと、jestがtest specをtranspileしてくれない。
{
"presets": ["env", "react"]
}
npm run test
を実行すると、__test__
の下に__snapshots__
が追加される。中にはbookのtest snapshotがある。
もう一回npm run test
を実行すると、↑のsnapshotを比べることになる。たとえばButtonの20px
をうっかりと21px
にしちゃった場合、run testでエラーが吐かれる。とっても便利。(dynamic testingするときは別の話ですが)
storybookに戻ります。storybookの書き方はtest spec に似てるのはお気づきでしょうか。同じくcomponentに必要なpropsをいれてinstance化としてる。そうであれば、ロジックが共有できそう。
storyshots
ってプラグインをインストール
npm i -D @storybook/addon-storyshots
storyshots.test.js
を追加
import initStoryshots from '@storybook/addon-storyshots';
initStoryshots({});
npm run test
を実行するsnapshotが2個追加される。Buttonの20px
を21px
にすると、エラーが2個吐かれる。
snapshotを更新するときもあるので、package.jsonでコマンドを追加すれば
"update-snapshot": "jest --updateSnapshot --no-watchman"
うん、便利ですね。
サマリー
以上storybookの紹介でした。いかがでしょうか。自分のプロジェクトは結構使っていい感じでしたので、よければぜひ試してみてください。
以上では各投稿者の観点であり、zanp.lifeに責任負い兼ねます。
#js#programming#javascript#react#storybook#web#frontend