@storybook/react-nativeが v6.5にバージョンアップしたので移行した。 結構書き方が変わったので紹介
PR
Storybook v5 → v6で変わった内容
Component Story Format (CSF) がサポートされた
Storybookのファイルの書きからが以下のように変更。
■ 既存
import React from 'react'; import { storiesOf } from '@storybook/react-native'; import { View } from 'react-native'; import Text from './'; storiesOf('atoms', module).add('Text', () => ( <View> <Text>default</Text> </View> ));
■ 新規
import React from 'react'; import { View } from 'react-native'; import Text from '.'; const Story = () => ( <View> <Text>default</Text> </View> ); export default { title: 'atoms/Text', component: Story, }; export const Default = {};
上記みたいな感じでstoriesOf
は使わず、export
することでstorybookの表示が行える。
Storybook v6.5への移行作業
以下の記事を参考に移行作業をした。
まず、.storybook
のフォルダを作成して以下のexampleのリポジトリを参考にファイルを配置
package.jsonに以下を追加
"scripts": { ...(略) "start-server": "react-native-storybook-server", "storybook-generate": "sb-rn-get-stories", "storybook-watch": "sb-rn-watcher", "storybook": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start", "storybook:ios": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start --ios", "storybook:android": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start --android",
次に既存のstoryファイルを移行。 storybookがマイグレーション用のコマンドを用意してくれているので、以下のコマンドを実行で自動的変換できる。
$ npx storybook@next migrate storiesof-to-csf --glob="src/**/*.stories.tsx"
※上記のコマンドで変換されるのは、CSF1のフォーマットなので注意。現状の最新はCSF3なので、そちらに変換したい場合は、CSF1に変更後に手動で修正する必要がある(CSF1でも動作はするので、今回はこのまま実装)
memoirには既存で以下のように、1つのstoryファイルに複数のComponentのstoryを表示しているファイルがあった。以下のようなファイルはコマンドではうまく変換できなかった。
■ src/components/organisms/Memoir/stories.tsx
import React from 'react'; import { storiesOf } from '@storybook/react-native'; (略) storiesOf('organisms/Memoir/DateCards', module) .add('default', () => ( <View style={styles.root}> <DateCards {...props()} /> </View> )) .add('loading', () => ( <View style={styles.root}> <DateCards {...props()} loading /> </View> )); storiesOf('organisms/Memoir', module).add('Card', () => ( <Card {...item()} user={{ id: 'test', displayName: 'suzuki', image: 'https://placehold.jp/150x150.png', }} /> )); storiesOf('organisms/Memoir/ScreenShot', module).add('default', () => ( <View style={styles.root}> <ScreenShot {...screenShotProps()} /> </View> ));
CSFは1ファイル、1Componentのフォーマットになっているので、以下のスクリプトを作成して、既存のstories.tsx
をrename
■ scripts/storybookRename/main.js
const fs = require('fs'); const path = require('path'); const dirPath = 'src/components'; const traverseDirectory = (dir, callback) => { fs.readdirSync(dir).forEach((file) => { const fullPath = path.resolve(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { traverseDirectory(fullPath, callback); } else { callback(fullPath); } }); }; traverseDirectory(dirPath, (filePath) => { const dirname = path.dirname(filePath); const basename = path.basename(filePath); if (basename === 'stories.tsx') { const newBasename = `${path.basename(dirname)}.${basename}`; const newPath = path.resolve(dirname, newBasename); fs.renameSync(filePath, newPath); console.log(`Renamed: ${filePath} --> ${newPath}`); } });
上記のスクリプトを実行して、stories.tsx
→Text.stories.tsx
にrenameしてフォーマットをCSFに合わせていった。
CSFの変換完了後は以下のコマンドで実行。
まず、以下のコマンドでstorybook-serverを起動。
$ yarn start-server
次に以下のコマンドでstorybookを起動。
$ yarn storybook:ios
これで以下の通りに起動ができた。
@storybook/react-nativeはv5で大分更新が止まっていたのでweb版に移行も検討していた。 ただ、web版だとNative固有のコードが動かせないので困るなーと思っていたので更新がきてよかったです。