• トップ
  • ブログ一覧
  • 【ReactNative】Storybookを導入した話
  • 【ReactNative】Storybookを導入した話

    概要

    Storybookはコンポーネントを一覧表示できるツールです。

    ページ自体を実装することなくコンポーネントを個別に表示できるため、
    単体のコンポーネント実装やコードレビューに便利です。

    私の担当しているReactNativeプロジェクトで大規模なページ実装があり、
    大量のコンポーネントが必要になるため導入してみました。

    今回はExpoでのStorybookの導入を紹介します!

    導入

    以下を実行してStorybookをインストールします。
    途中でいくつか選択肢が出てきますが、初期選択のもので進めて問題ありません。

    1npm create storybook@latest
    2npx expo@latest customize metro.config.js

    次にmetro.config.jsを編集し、withStorybookを追加しましょう。

    1// module.exports = config; こちらは削除
    2const { withStorybook } = require('@storybook/react-native/metro/withStorybook');
    3module.exports = withStorybook(config);

    app/storybook.tsxファイルを追加して以下を設定します。

    1export { default } from '@storybook/react-native';

    _layout.tsxを編集してStorybookを組み込みます

    1<Stack.Protected guard={__DEV__}>
    2  <Stack.Screen name="storybook" options={{headerShown: false}} />
    3</Stack.Protected>

    あとは適当なファイルにStorybookへの遷移を実装しましょう!

    1<Link href="/storybook">Open Storybook</Link>

    これでStorybookの導入が完了しました!
    ページを開くことで.rnstorybookに入っているサンプルコンポーネントが一覧表示されます。

     

    自前のコンポーネントを追加する

    次に自身が作成したコンポーネントをStorybookに追加してみましょう!

    まずはStorybookとして読み込むフォルダを指定していきます。
    .rnstorybook/main.tsを開いてstoriesをコンポーネントフォルダ向けに変更しましょう。

    1import type { StorybookConfig } from '@storybook/react-native';
    2
    3const main: StorybookConfig = {
    4  stories: ['../components/*/*.stories.?(ts|tsx|js|jsx)'],
    5  addons: ['@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-actions'],
    6};
    7
    8export default main;

    そのあとnpm run startを再度実施し、
    .rnstorybook/storybook.requires.tsに設定を反映させます。

    そうしたらいよいよStorybookファイルを作っていくわけですが、
    今回は以下の簡単なボタンコンポーネントを対象に作成していきます。

    1// components/testButton/index.tsx
    2import { Text, TouchableOpacity } from "react-native";
    3
    4type Props = {
    5  color: 'blue' | 'red';
    6  onPress?: () => void;
    7}
    8
    9export function TestButton({ color, onPress }: Props) {
    10  return (
    11    <TouchableOpacity onPress={onPress}>
    12      <Text style={{
    13        color: color, fontSize: 24,
    14      }}>タップしてください</Text>
    15    </TouchableOpacity>
    16  )
    17}

    同じフォルダ内にindex.stories.tsxを追加します。

    1// components/testButton/index.stories.tsx
    2import { Meta, StoryFn, StoryObj } from "@storybook/react-native";
    3import { useState } from "react";
    4import { Text, View } from "react-native";
    5import { TestButton } from "./index";
    6
    7const meta = {
    8  title: 'components/testButton',
    9  component: TestButton,
    10} satisfies Meta<typeof TestButton>;
    11
    12export default meta;
    13
    14type Story = StoryObj<typeof meta>;
    15
    16// Propsのみの簡易的な設定
    17export const Blue: Story = {
    18  args: {
    19    color: 'blue',
    20  },
    21};
    22
    23// StoryFnを利用することで、hooksなども利用可能
    24export const Red: StoryFn = () => {
    25  const [countup, setCountup] = useState(0);
    26  return (
    27    <View style={{ flex: 1 }}>
    28      <TestButton
    29        color="red"
    30        onPress={() => {
    31          setCountup(countup + 1);
    32        }}
    33      />
    34      <Text style={{ fontSize: 24 }}>押された回数: {countup}</Text>
    35    </View>
    36  )
    37};

    これでStorybookページにTestButtonが追加され、Blue/Redそれぞれ表示できるようになりました!

    testButton/BluetestButton/Red

    まとめ

    Storybookを導入することでコンポーネント単体で動作するページが作成できるので、
    コンポーネントの動作確認がしやすくなります。

    導入も簡単なので是非利用してみてください!

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background