すべての UI コンポーネントを React 内の特定の場所に配置しようとしたことはありますか?
React の世界に慣れていない人は、おそらく知らないでしょう。
それはどういう意味ですか?
反応-美しい-dnd の 例を参照してください。
例で見たものは ストーリー と呼ばれます。ストーリーの作成に使用されるツールは Storybook と呼ばれます。
これで、この記事で説明する内容が理解できたでしょう。早速、探索してみましょう。
ストーリーブックとは何ですか?
Storybook は、 コンポーネントのプレイグラウンドを提供する、ユーザー インターフェイスに分離された開発環境です。メインアプリを実行しなくても、コンポーネントをさまざまな方法で操作できます。セットアップを使用して、ポート内でストーリーブックを実行できます。
Reactに限った話ではありません。 Storybook は 、Vue、Angular、Mithril、Marko、Svelte などのほとんどのフロントエンド フレームワークで使用できます。
ストーリーブックの詳細については 、こちらを ご覧ください。
物語とは何ですか?
ストーリーは、コンポーネントのレンダリング状態を定義します。共通のコンポーネントを取得した場合、それを props を使用してさまざまな方法で使用できます。それらの州ごとにストーリーを書くことができます。
Button コンポーネントがあるとします。
ボタン は、無効、読み込み中、プライマリ、セカンダリ、小、大、中などのさまざまな状態で存在できます。 すべての状態をリストすると、チュートリアルを進めるのが非常に困難になります。お分かりかと思います。ストーリーブックを読み始めると、さらに理解できるようになります。
ボタンのストーリーをケース別に(大・中・小)見ることができます。
プロジェクトでストーリーブックを設定する
React プロジェクトでストーリーブックをセットアップします。
さあ行こう。
- 以下のコマンドで反応プロジェクトを作成します。好きな名前を付けることができます。
npx create-react-app storybook-demo
- 次に、次のコマンドを使用してプロジェクトに ストーリーブック をインストールします。
npx sb init
ストーリーブックのセットアップが完了しました。
ストーリーブックは別のサーバーを提供します。
どうやって始めますか?
ストーリーブックはスクリプト ファイルにコマンドを自動的に追加します。 スクリプト セクション内の package.json ファイルで確認できます。とりあえず、次のコマンドを実行してストーリーブックサーバーを起動します。
npm run storybook
Storybook は、 package.json ファイルの script セクションで指定されたポートで新しいサーバーを起動します。デフォルトのブラウザ (反応サーバーと同じ) でストーリーブックが自動的に開きます。
デフォルトでは、さまざまなストーリーが表示されます。不要な場合は削除したり、参照用に保存したりできます。前のセクションで説明したように、ボタンは複数の状態を持つことができ、ストーリーブックでそれらを確認できます (すべての状態が記載されているわけではありません)。このチュートリアルの最後のセクションでは、ボタン用の大規模なストーリー セットを作成します。
ストーリーブックのさまざまなセクションを調べて、さまざまなセクションに慣れてください。このチュートリアルでは、そのうちのいくつかについて説明します。
最初の物語を書いてみましょう。
テストのストーリーブック
私たちはストーリーブックが実行され、その中にいくつかの例があるのを見てきました。
- src フォルダー内に Button というフォルダーを作成します。
- Button.jsx、 Button.css 、 constants.js というファイルを作成します。
- 以下のスニペットのそれぞれのコードをファイルに配置します。
ボタン.jsx
import React, { Component } from "react";
import PropTypes from "prop-types";
import "./Button.css";
import { buttonTypes, buttonVariants, buttonSizes } from "./constants";
class Button extends Component {
static defaultProps = {
isDisabled: false,
type: "filled",
variant: "oval",
size: "medium",
backgroundColor: "#1ea7fd",
textColor: "#ffffff",
};
static buttonTypes = buttonTypes;
static buttonVariants = buttonVariants;
static buttonSizes = buttonSizes;
renderButton = () => {
const {
text,
isDisabled,
type,
variant,
size,
backgroundColor,
textColor,
onClick,
} = this.props;
return (
<button
onClick={onClick}
className={`default ${variant} ${size} ${
isDisabled ? "disabled" : ""
}`}
style={
type === buttonTypes.outline
? {
border: `1px solid ${backgroundColor}`,
color: "#000000",
backgroundColor: "transparent",
}
: {
backgroundColor: `${backgroundColor}`,
border: `1px solid ${backgroundColor}`,
color: textColor,
}
}
disabled={isDisabled}
>
{text}
</button>
);
};
render() {
return this.renderButton();
}
}
Button.propTypes = {
text: PropTypes.string,
isDisabled: PropTypes.bool,
type: PropTypes.oneOf([buttonTypes.outline, buttonTypes.filled]),
variant: PropTypes.oneOf([buttonVariants.oval, buttonVariants.rectangular]),
size: PropTypes.oneOf([
buttonSizes.small,
buttonSizes.medium,
buttonSizes.large,
]),
backgroundColor: PropTypes.string,
textColor: PropTypes.string,
onClick: PropTypes.func,
};
export { Button };
ボタン.css
.default {
border: none;
cursor: pointer;
background-color: transparent;
}
.default:focus {
outline: none;
}
.disabled {
opacity: 0.75;
cursor: not-allowed;
}
.small {
font-size: 12px;
padding: 4px 8px;
}
.medium {
font-size: 14px;
padding: 8px 12px;
}
.large {
font-size: 16px;
padding: 12px 16px;
}
.oval {
border-radius: 4px;
}
.rectangular {
border-radius: 0;
}
定数.js
export const buttonTypes = {
outline: "outline",
filled: "filled",
};
export const buttonVariants = {
oval: "oval",
rectangular: "rectangular",
};
export const buttonSizes = {
small: "small",
medium: "medium",
large: "large",
};
そのコードは何ですか?
さまざまな方法で使用できる Button の共通コンポーネントを作成しました。これで、さまざまな状態を持つことができるコンポーネントができました。
以下の手順に従って、最初のストーリーを書いてみましょう。
- Button.stories.jsx というファイルを作成します。
- React と Button コンポーネントをファイルにインポートします。
- 次に、コンポーネント ストーリーのタイトルまたはパスを定義します。次のコードを使用して定義します。
export default {
title: ‘common/Button’,
}
- 次のように、必須の小道具を含むボタンをエクスポートします。
export const defaultButton = () => (
<Button text=”Default Button” onClick={() => {}} />
);
最初のストーリーが完成しました。次のコマンドを使用してストーリーブックを実行し、出力を確認します。
npm run storybook
フロントエンド開発にどのように役立ちますか?
ストーリーブックを使用する主な利点は何ですか?
10人のメンバーからなるチームで働いているとします。そして、現在作業中のプロジェクト用に全員が作成した共通コンポーネントをチェックする必要があります。
どうすればそれができるでしょうか?
それらをチェックするには、すべての共通コンポーネントにアクセスする必要があります。しかし、それは時間がかかり、私たちにとって好ましい方法ではありません。新しいゲスト ストーリーブック が登場しました。
問題を解決するためにそれをどのように活用すればよいでしょうか?
ストーリーブックを使用して、共通コンポーネント (任意の UI コンポーネント) のストーリーを作成できます。そして、チームメイトが他のチームの共通コンポーネントをチェックしたいときはいつでも、ストーリーブック サーバーを実行するだけで、上で見たようにそこにあるすべての UI コンポーネントが表示されます。
ストーリーブック内でレンダリングされたコンポーネントを使用して、さらに多くのことができます。 Storybook には、ストーリーにスーパーパワーを与える アドオン と呼ばれる概念があります。
ストーリーブック自体の UI コンポーネントの応答性をチェックする必要があるとします。ストーリーブックで Viewport と呼ばれるアドオンを使用できます。アドオンについては次のセクションで詳しく説明します。
ストーリーブックの操作
このセクションでは、共通コンポーネント Button のさまざまな状態を定義するさまざまなストーリーを書きます。
物語を書くことはそれほど難しいことではありません。ストーリーはコンポーネントの状態を定義します。コンポーネントのプロパティを見れば、コンポーネントのさまざまな使用例を簡単に理解できます。
オプションの小道具を与えてストーリーを書いてみましょう。
export const largeButton = () => (
<Button text="Large Button" onClick={() => {}} size="large" />
);
export const outlineSmallButton = () => (
<Button
text="Outline Small Button"
onClick={() => {}}
size="small"
type="outline"
/>
);
export const rectangularLargeButton = () => (
<Button
text="Rectangular Large Button"
onClick={() => {}}
size="large"
variant="rectangular"
/>
);
export const disabledButton = () => (
<Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);
export const warningButton = () => (
<Button
text="Warning Button"
onClick={() => {}}
backgroundColor="orange"
/>
);
上記の 3 つのストーリーは、コンポーネント Button のさまざまな使用例を定義しています。次に、共通コンポーネントにストーリーの他のケースをいくつか追加する番です。 disabledSamllRectangularButton、dangerButton、successDisabledButton などを追加してみてください。
上記の場合のコードは提供しません。それを理解するには自分で書かなければなりません。これまでに作成した完全なストーリー コードを確認できます。
import React from "react";
import { Button } from "./Button";
export default {
title: "src/common/Button",
};
export const defaultButton = () => (
<Button text="Default Button" onClick={() => {}} />
);
export const largeButton = () => (
<Button text="Large Button" onClick={() => {}} size="large" />
);
export const outlineSmallButton = () => (
<Button
text="Outline Small Button"
onClick={() => {}}
size="small"
type="outline"
/>
);
export const rectangularLargeButton = () => (
<Button
text="Rectangular Large Button"
onClick={() => {}}
size="large"
variant="rectangular"
/>
);
export const disabledButton = () => (
<Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);
export const warningButton = () => (
<Button
text="Disabled Button"
onClick={() => {}}
backgroundColor="orange"
/>
);
これで、コンポーネントのストーリーを書く方法を完全に理解できました。
次のセクションに進み、アドオンについて、そしてアドオンがどのようにストーリーを強化するかを学びましょう。
ストーリーブック アドオン
デフォルトでは複数のアドオンが利用可能になります。このセクションでは、開発に最も役立つアドオンを検討します。
Button のストーリーを盛り上げていきましょう。
コントロール
コントロールは、ストーリーブック自体のコンポーネントにカスタムの小道具を与える機能を追加します。 Button コンポーネントには、ストーリーブック内のさまざまなプロップを変更するコントロールを追加できます。
ボタンの背景色に最適な色を見つける必要があるとします。コンポーネントにいちいち背景色を与えてテストしていたら時間がかかってしまいます。代わりに、ストーリーブック内で別の色を選択できるコントロールを追加できます。ストーリーブック自体の背景色をテストできます。
ボタン ストーリーにコントロールを追加する方法を見てみましょう。
まず、タイトルの下にあるすべてのプロパティを次のように定義する必要があります。
export default {
title: "src/common/Button",
argTypes: {
text: { control: "text" },
backgroundColor: { control: "color" },
isDisabled: { control: "boolean" },
size: {
control: { type: "select", options: ["small", "medium", "large"] },
},
type: {
control: { type: "select", options: ["filled", "outline"] },
},
variant: {
control: { type: "select", options: ["oval", "rectangular"] },
},
},
};
次に、次のようにコンポーネントから props を分離し、 引数 として与えます。
export const outlineSmallButton = (args) => (
<Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
text: "Outline Small Button",
size: "small",
type: "outline",
};
コンポーネントのプレビュー ウィンドウの下部にコントロールが表示されます。
コンポーネントのプレビュー ウィンドウの下部に コントロール タブが表示されます。周りで遊んでみてください。
上記のようにすべてのストーリーを更新します。これは、ストーリーブック アドオンの構文を知ることに似ています。 argTypes では、さまざまなタイプのコントロールを使用しました。ストーリーブックに存在するすべての コントロールは 、 ここで 見つけることができます。
更新されたボタンストーリーは次のようになります。
import React from "react";
import { Button } from "./Button";
export default {
title: "src/common/Button",
argTypes: {
text: { control: "text" },
backgroundColor: { control: "color" },
isDisabled: { control: "boolean" },
size: {
control: { type: "select", options: ["small", "medium", "large"] },
},
type: {
control: { type: "select", options: ["filled", "outline"] },
},
variant: {
control: { type: "select", options: ["oval", "rectangular"] },
},
},
};
export const defaultButton = (args) => <Button {...args} onClick={() => {}} />;
defaultButton.args = {
text: "Default Button",
};
export const largeButton = (args) => (
<Button {...args} onClick={() => {}} size="large" />
);
largeButton.args = {
text: "Large Button",
};
export const outlineSmallButton = (args) => (
<Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
text: "Outline Small Button",
size: "small",
type: "outline",
};
export const rectangularLargeButton = (args) => (
<Button {...args} onClick={() => {}} />
);
rectangularLargeButton.args = {
text: "Rectangular Large Button",
size: "large",
variant: "rectangular",
};
export const disabledButton = (args) => <Button {...args} onClick={() => {}} />;
disabledButton.args = {
text: "Disabled Button",
isDisabled: true,
};
export const warningButton = (args) => <Button {...args} onClick={() => {}} />;
warningButton.args = {
text: "Warning Button",
backgroundColor: "orange",
};
行動
アクションは JavaScript の イベント です。 JavaScript ではイベントであるボタンをクリックできます。 アクション アドオン を使用して、ボタンのクリック時にいくつかの アクション を実行できます。
アクションを使用すると、イベントが適切に動作しているかどうかをテストできます。無効なボタンはクリックできませんが、有効なボタンはクリック可能である必要があります。 アクションを 使用してそれを保証できます。
ボタンのクリックにアクションを追加する方法を見てみましょう。
以前に onClick プロパティに匿名関数を与えました。さて、更新する必要があります。
- 次のステートメントを使用して、ストーリーブック アドオンからアクションをインポートします。
import { action } from "@storybook/addon-actions";
- すべての () => {} を次のステートメントに置き換えます。
action("Button is clicked!")
次に、ストーリーブックに移動してボタンをクリックします。 「コントロール」 タブの横にある 「アクション」 タブの下にメッセージが表示されます。 「無効」ボタンをクリックしても無効になっているため、メッセージは印刷されません。
onChange、onMouseOver、onMouseOut などのさまざまなイベントに アクション を使用して、それらが適切に動作していることを確認できます。 input 要素の onChange にも同じことを実装してみてください。
アクション については 、こちらの ドキュメントを参照してください。
背景
背景アドオンを使用してプレビュー ウィンドウの背景を変更できます。コードを記述する必要はありません。ストーリーブック内で変更するだけです。以下のGIFをご覧ください。
ビューポート
ストーリーブック内のコンポーネントの応答性をテストすることもできます。ビューポート オプションについては、以下の gif を参照してください。
ドキュメント
ドキュメント アドオンを使用して、ストーリーブック内のコンポーネントを文書化できます。チームで作業するときにさらに便利です。彼らはコンポーネントを読んで直接理解します。開発者にとっては時間を大幅に節約できます。
ストーリーブックのコンポーネントのプレビュー ウィンドウでは、右上の [キャンバス] タブに ドキュメント が表示されます。これには、コンポーネントのすべてのストーリーのすべてのドキュメントが含まれます。マークダウンとコンポーネントのレンダリングの両方を含むコンポーネントのドキュメントを作成したい場合は、 Button.stories.mdx を使用する必要があります。コンポーネントのストーリーとともに、その中に追加のマークダウン コードを記述するだけです。
私たちはストーリーのための文書を書いています。コードにはマークダウンとコンポーネントのレンダリングが含まれます。すべては構文を学習するだけです。ひと目でわかります。
Button.stories.mdx ドキュメント コードを見てみましょう。
<!--- Button.stories.mdx -->
import {
Meta,
Story,
Preview,
ArgsTable
} from '@storybook/addon-docs/blocks';
import { Button } from './Button';
<Meta title="MDX/Button" component={Button} />
# Button Documentation
With `MDX` we can define a story for `Button` right in the middle of our
Markdown documentation.
<ArgsTable of={Button} />
export const Template = (args) => <Button {...args} />
## Default Button
We can write the documentation related to the Default Button
<Preview>
<Story name="Default Button" args={{
text: 'Default Button'
}}>
{Template.bind({})}
</Story>
</Preview>
## Large Button
We are writing sample docs for two stories, you can write rest of them
<Preview>
<Story name="Large Button" args={{
text: "Large Button",
}}>
{Template.bind({})}
</Story>
</Preview>
文書化コンポーネントの詳細については 、こちらを ご覧ください。
アドオンの詳細については 、こちらを ご覧ください。
結論
チュートリアルを楽しんで、ストーリーブックについて学んでいただければ幸いです。そして、それをチーム内で効果的に活用して、仕事の生産性を高めましょう。
React は初めてですか?これらの学習リソースを確認してください。
コーディングを楽しんでください 🙂