From cfd7bdeeb44183d8162aee6e5071c886de930934 Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Thu, 16 May 2024 19:33:00 +0900
Subject: [PATCH 01/14] Update get-started.md
---
.../react/ja/get-started.md | 23 +++++++------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/content/intro-to-storybook/react/ja/get-started.md b/content/intro-to-storybook/react/ja/get-started.md
index c84ecd3e4..60cd0fa5e 100644
--- a/content/intro-to-storybook/react/ja/get-started.md
+++ b/content/intro-to-storybook/react/ja/get-started.md
@@ -16,12 +16,12 @@ Storybook を開発プロセスに組み込むにあたり、いくつかの手
それでは、次のコマンドを実行してください:
```shell:clipboard=false
-# Clone the template
+# テンプレートをクローンする
npx degit chromaui/intro-storybook-react-template taskbox
cd taskbox
-# Install dependencies
+# 依存関係をインストールする
yarn
```
@@ -32,23 +32,16 @@ yarn
それでは、アプリケーションのさまざまな環境が問題なく動くことを次のコマンドで確認しましょう:
```shell:clipboard=false
-# Run the test runner (Jest) in a terminal:
-yarn test --watchAll
-
-# Start the component explorer on port 6006:
+# コンポーネントエクスプローラを6006番ポートで起動する
yarn storybook
-# Run the frontend app proper on port 3000:
-yarn start
+# フロントエンドアプリケーションを5173番ポートで起動する
+yarn dev
```
-
💡 Git へのコミットを忘れずに行ってください!
From 734b40152392d27018c4fafacffaa8aa410b5b19 Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Thu, 16 May 2024 20:19:01 +0900
Subject: [PATCH 03/14] Update composite-component.md
---
.../react/ja/composite-component.md | 156 ++++++++++++------
1 file changed, 101 insertions(+), 55 deletions(-)
diff --git a/content/intro-to-storybook/react/ja/composite-component.md b/content/intro-to-storybook/react/ja/composite-component.md
index 127172d7b..68b8952f2 100644
--- a/content/intro-to-storybook/react/ja/composite-component.md
+++ b/content/intro-to-storybook/react/ja/composite-component.md
@@ -9,21 +9,21 @@ commit: '429780a'
## TaskList (タスクリスト)
-Taskbox はピン留めされたタスクを通常のタスクより上部に表示することで強調します。これにより `TaskList` に、タスクのリストが、通常のタスクのみである場合と、ピン留めされたタスクとの組み合わせである場合という、ストーリーを追加するべき 2 つのバリエーションができます。
+Taskbox はピン留めされたタスクを通常のタスクより上部に表示することで強調します。これにより `TaskList` に、タスクのリストが通常のタスクのみである場合とピン留めされたタスクとの組み合わせである場合という、ストーリーを追加するべき 2 つのバリエーションができます。
![通常のタスクとピン留めされたタスク](/intro-to-storybook/tasklist-states-1.png)
-`Task` のデータは非同期的に送信されるので、接続がないことを示すため、読み込み中の状態**も**必要となります。さらにタスクがない場合に備え、空の状態も必要です。
+`Task` のデータは非同期的に送信されるので、接続がないことを示すため、読み込み中の状態**も併せて**必要となります。さらにタスクがない場合に備え、空の状態も必要です。
![空の状態と読み込み中の状態](/intro-to-storybook/tasklist-states-2.png)
## セットアップする
-複合的なコンポーネントも基本的なコンポーネントと大きな違いはありません。`TaskList` のコンポーネントとそのストーリーファイル、`src/components/TaskList.js` と `src/components/TaskList.stories.js` を作成しましょう。
+複合的なコンポーネントも基本的なコンポーネントと大きな違いはありません。`TaskList` のコンポーネントとそのストーリーファイル、`src/components/TaskList.jsx` と `src/components/TaskList.stories.jsx` を作成しましょう。
まずは `TaskList` の大まかな実装から始めます。前の章で作成した `Task` コンポーネントをインポートし、属性とアクションを入力として渡します。
-```js:title=src/components/TaskList.js
+```jsx:title=src/components/TaskList.jsx
import React from 'react';
import Task from './Task';
@@ -54,61 +54,61 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
次に `Tasklist` のテスト状態をストーリーファイルに記述します。
-```js:title=src/components/TaskList.stories.js
-import React from 'react';
-
+```jsx:title=src/components/TaskList.stories.jsx
import TaskList from './TaskList';
+
import * as TaskStories from './Task.stories';
export default {
component: TaskList,
title: 'TaskList',
- decorators: [story =>
{story()}
],
+ decorators: [(story) =>
{story()}
],
+ tags: ['autodocs'],
};
-const Template = args =>
;
-
-export const Default = Template.bind({});
-Default.args = {
- // Shaping the stories through args composition.
- // The data was inherited from the Default story in Task.stories.js.
- tasks: [
- { ...TaskStories.Default.args.task, id: '1', title: 'Task 1' },
- { ...TaskStories.Default.args.task, id: '2', title: 'Task 2' },
- { ...TaskStories.Default.args.task, id: '3', title: 'Task 3' },
- { ...TaskStories.Default.args.task, id: '4', title: 'Task 4' },
- { ...TaskStories.Default.args.task, id: '5', title: 'Task 5' },
- { ...TaskStories.Default.args.task, id: '6', title: 'Task 6' },
- ],
+export const Default = {
+ args: {
+ // argsによってストーリーを形成します。
+ // データはTask.stories.jsxのDefaultストーリーから継承しています。
+ tasks: [
+ { ...TaskStories.Default.args.task, id: '1', title: 'Task 1' },
+ { ...TaskStories.Default.args.task, id: '2', title: 'Task 2' },
+ { ...TaskStories.Default.args.task, id: '3', title: 'Task 3' },
+ { ...TaskStories.Default.args.task, id: '4', title: 'Task 4' },
+ { ...TaskStories.Default.args.task, id: '5', title: 'Task 5' },
+ { ...TaskStories.Default.args.task, id: '6', title: 'Task 6' },
+ ],
+ },
};
-export const WithPinnedTasks = Template.bind({});
-WithPinnedTasks.args = {
- // Shaping the stories through args composition.
- // Inherited data coming from the Default story.
- tasks: [
- ...Default.args.tasks.slice(0, 5),
- { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
- ],
+export const WithPinnedTasks = {
+ args: {
+ tasks: [
+ ...Default.args.tasks.slice(0, 5),
+ { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
+ ],
+ },
};
-export const Loading = Template.bind({});
-Loading.args = {
- tasks: [],
- loading: true,
+export const Loading = {
+ args: {
+ tasks: [],
+ loading: true,
+ },
};
-export const Empty = Template.bind({});
-Empty.args = {
- // Shaping the stories through args composition.
- // Inherited data coming from the Loading story.
- ...Loading.args,
- loading: false,
+export const Empty = {
+ args: {
+ // argsによってストーリーを形成します。
+ // データは上のLoadingストーリーから継承しています。
+ ...Loading.args,
+ loading: false,
+ },
};
```
-💡
デコレーターを使ってストーリーに任意のラッパーを設定できます。上記のコードでは、
decorators
というキーをデフォルトエクスポートに追加し、描画するコンポーネントの周りに
padding
を設定してます。ストーリーで使用する「プロバイダー」(例えば、React のコンテキストを設定するライブラリコンポーネントなど) を使うためにも使用します。
+💡
デコレーターを使ってストーリーに任意のラッパーを設定できます。上記のコードでは、
decorators
というキーをデフォルトエクスポートに追加し、描画するコンポーネントの周りに
padding
を設定しています。ストーリーで使用する「プロバイダー」(例えば、React のコンテキストを設定するライブラリコンポーネントなど) を使うためにも使用します。
`TaskStories` をインポートすることで、ストーリーに必要な引数 (args) を最小限の労力で[組み合わせる](https://storybook.js.org/docs/react/writing-stories/args#args-composition)ことができます。そうすることで、2 つのコンポーネントが想定するデータとアクション (呼び出しのモック) の一貫性が保たれます。
@@ -117,16 +117,16 @@ Empty.args = {
## 状態を作りこむ
-今のコンポーネントはまだ粗削りですが、ストーリーは見えています。単に `.list-items` だけのためにラッパーを作るのは単純すぎると思うかもしれません。実際にその通りです。ほとんどの場合単なるラッパーのためだけに新しいコンポーネントは作りません。`TaskList` の**本当の複雑さ**は `withPinnedTasks`、`loading`、`empty` といったエッジケースに現れているのです。
+今のコンポーネントはまだ粗削りですが、ストーリーは見えています。単に `.list-items` だけのためにラッパーを作るのは単純すぎると思うかもしれません。実際、その通りです。ほとんどの場合、単なるラッパーのためだけに新しいコンポーネントは作りません。`TaskList` の**本当の複雑さ**は `withPinnedTasks`、`loading`、`empty` といったエッジケース(ユーザーが遭遇する可能性のあるまれなバグ)に現れているのです。
-```js:title=src/components/TaskList.js
+```jsx:title=src/components/TaskList.jsx
import React from 'react';
import Task from './Task';
@@ -161,16 +161,16 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
-
You have no tasks
-
Sit back and relax
+
You have no tasks
+
Sit back and relax
);
}
const tasksInOrder = [
- ...tasks.filter((t) => t.state === "TASK_PINNED"),
- ...tasks.filter((t) => t.state !== "TASK_PINNED"),
+ ...tasks.filter((t) => t.state === 'TASK_PINNED'),
+ ...tasks.filter((t) => t.state !== 'TASK_PINNED'),
];
return (
@@ -186,7 +186,7 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
@@ -197,24 +197,70 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
コンポーネントが大きくなるにつれ、入力の要件も増えていきます。`TaskList` のプロパティの要件を定義しましょう。`Task` が子供のコンポーネントなので、`Task` を表示するのに正しいデータ構造が渡されていることを確認しましょう。時間を節約するため、前の章で `Task` に定義した `propTypes` を再利用しましょう。
-```diff:title=src/components/TaskList.js
+```diff:title=src/components/TaskList.jsx
import React from 'react';
+ import PropTypes from 'prop-types';
import Task from './Task';
export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
- ...
+ const events = {
+ onPinTask,
+ onArchiveTask,
+ };
+ const LoadingRow = (
+
+
+
+ Loading cool state
+
+
+ );
+ if (loading) {
+ return (
+
+ {LoadingRow}
+ {LoadingRow}
+ {LoadingRow}
+ {LoadingRow}
+ {LoadingRow}
+ {LoadingRow}
+
+ );
+ }
+ if (tasks.length === 0) {
+ return (
+
+
+
+
You have no tasks
+
Sit back and relax
+
+
+ );
+ }
+
+ const tasksInOrder = [
+ ...tasks.filter((t) => t.state === 'TASK_PINNED'),
+ ...tasks.filter((t) => t.state !== 'TASK_PINNED'),
+ ];
+ return (
+
+ {tasksInOrder.map((task) => (
+
+ ))}
+
+ );
}
+ TaskList.propTypes = {
-+ /** Checks if it's in loading state */
++ /** ローディング状態かどうかをチェックする */
+ loading: PropTypes.bool,
-+ /** The list of tasks */
++ /** タスクの配列 */
+ tasks: PropTypes.arrayOf(Task.propTypes.task).isRequired,
-+ /** Event to change the task to pinned */
++ /** タスクのをの状態を「ピン留め済」に変更するイベント */
+ onPinTask: PropTypes.func,
-+ /** Event to change the task to archived */
++ /** タスクの状態を「アーカイブ済」に変更するイベント */
+ onArchiveTask: PropTypes.func,
+ };
+ TaskList.defaultProps = {
From 2f9468d93005f28063796023ddc6add1430cab44 Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Thu, 16 May 2024 20:34:19 +0900
Subject: [PATCH 04/14] Update data.md
---
content/intro-to-storybook/react/ja/data.md | 151 ++++++++++----------
1 file changed, 76 insertions(+), 75 deletions(-)
diff --git a/content/intro-to-storybook/react/ja/data.md b/content/intro-to-storybook/react/ja/data.md
index f48bb0e9d..fd3289a70 100644
--- a/content/intro-to-storybook/react/ja/data.md
+++ b/content/intro-to-storybook/react/ja/data.md
@@ -13,7 +13,7 @@ commit: 'c70ec15'
`TaskList` コンポーネントは、今のところ「presentational (表示用)」として書かれており、その実装以外の外部とは何もやりとりをしません。データを中に入れるためにはデータプロバイダに繋ぐ必要があります。
-ここではデータを保存する際に使用される React で人気のライブラリーである [Redux](https://redux.js.org/) を使用し、アプリケーションにシンプルなデータモデルを作ります。[Apollo](https://www.apollographql.com/client/) や [MobX](https://mobx.js.org/) といった他のデータ管理用のライブラリーでもここでのパターンが使用できます。
+ここでは、[Redux](https://redux.js.org/) でデータを保存するためにもっとも効果的な開発用ツールセットである [Redux Toolkit](https://redux-toolkit.js.org/)を使用し、アプリケーションにシンプルなデータモデルを作ります。[Apollo](https://www.apollographql.com/client/) や [MobX](https://mobx.js.org/) といった他のデータ管理用のライブラリーでもここでのパターンが使用できます。
以下のコマンドを実行し必要な依存関係を追加しましょう:
@@ -24,14 +24,14 @@ yarn add @reduxjs/toolkit react-redux
まず、タスクの状態を変更するアクションを処理する単純な Redux のストアを作ります。`src/lib` フォルダの `store.js` というファイルを作ってください (あえて簡単にしています):
```js:title=src/lib/store.js
-/* A simple redux store/actions/reducer implementation.
- * A true app would be more complex and separated into different files.
+/* シンプルなreduxのストア/アクション/リデューサーの実装です。
+ * 本当のアプリケーションはもっと複雑で、異なるファイルに分けられます。
*/
import { configureStore, createSlice } from '@reduxjs/toolkit';
/*
- * The initial state of our store when the app loads.
- * Usually, you would fetch this from a server. Let's not worry about that now
+ * アプリケーションのロード時のストアの初期状態です。
+ * 通常、サーバーから取得しますが、今回は気にしないでください(ファイルに直書きしています)。
*/
const defaultTasks = [
{ id: '1', title: 'Something', state: 'TASK_INBOX' },
@@ -46,8 +46,8 @@ const TaskBoxData = {
};
/*
- * The store is created here.
- * You can read more about Redux Toolkit's slices in the docs:
+ * ストアはここで作成されます。
+ * Redux Toolkitのスライスについて詳しくはドキュメントを参照してください:
* https://redux-toolkit.js.org/api/createSlice
*/
const TasksSlice = createSlice({
@@ -64,12 +64,12 @@ const TasksSlice = createSlice({
},
});
-// The actions contained in the slice are exported for usage in our components
+// スライスに含まれるアクションはコンポーネントで使用するためにエクスポートされます
export const { updateTaskState } = TasksSlice.actions;
/*
- * Our app's store configuration goes here.
- * Read more about Redux's configureStore in the docs:
+ * アプリケーションのストアの設定はここにあります。
+ * ReduxのconfigureStoreについて詳しくはドキュメントを参照してください:
* https://redux-toolkit.js.org/api/configureStore
*/
const store = configureStore({
@@ -81,16 +81,16 @@ const store = configureStore({
export default store;
```
-次に、`TaskList` コンポーネントのデフォルトエクスポートを更新し、Redux のストアに 「connect (接続)」し、ストアから、気になるタスクのリストを描画します。
+次に、`TaskList` コンポーネントのデフォルトエクスポートを更新し、Redux のストアに「connect (接続)」し、ストアから気になるタスクのリストを描画します。
-```js:title=src/components/TaskList.js
+```jsx:title=src/components/TaskList.jsx
import React from 'react';
import Task from './Task';
import { useDispatch, useSelector } from 'react-redux';
import { updateTaskState } from '../lib/store';
export default function TaskList() {
- // We're retrieving our state from the store
+ // ストアから状態を取得します
const tasks = useSelector((state) => {
const tasksInOrder = [
...state.taskbox.tasks.filter((t) => t.state === 'TASK_PINNED'),
@@ -107,11 +107,11 @@ export default function TaskList() {
const dispatch = useDispatch();
const pinTask = (value) => {
- // We're dispatching the Pinned event back to our store
+ // ストアにピン留めされたタスクを送信します
dispatch(updateTaskState({ id: value, newTaskState: 'TASK_PINNED' }));
};
const archiveTask = (value) => {
- // We're dispatching the Archive event back to our store
+ // ストアにアーカイブされたタスクを送信します
dispatch(updateTaskState({ id: value, newTaskState: 'TASK_ARCHIVED' }));
};
const LoadingRow = (
@@ -139,8 +139,8 @@ export default function TaskList() {
-
You have no tasks
-
Sit back and relax
+
You have no tasks
+
Sit back and relax
);
@@ -161,21 +161,19 @@ export default function TaskList() {
}
```
-これで、Redux からデータを取得し、実際のデータでコンポ―ネントを生成できるようになりました。`src/app.js` に接続してコンポーネントを描画することも可能ですが、今のところはこのままにして、コンポーネント駆動の旅を続けましょう。
+これで、Redux からデータを取得し、実際のデータでコンポーネントを生成できるようになりました。`src/app.js` に接続してコンポーネントを描画することも可能ですが、今のところはこのままにして、コンポーネント駆動の旅を続けましょう。
-アプリケーションで表示する方法は次の章で説明しますのでご心配なく。
+アプリケーションで表示する方法は次の章で説明しますので心配ありません。
## デコレーターにコンテキストを渡す
この段階で、Storybook のテストが動かなくなりました。`TaskList` が繋がれたコンポーネントとなって、タスクを取得しアップデートするのに Redux ストアに依存しているからです。
-![壊れたタスクリスト](/intro-to-storybook/broken-tasklist-optimized.png)
+![壊れたタスクリスト](/intro-to-storybook/broken-tasklist-7-0-optimized.png)
-この問題を解決するために、さまざまなアプローチができます。しかし、私たちのアプリは非常に単純なので、[前の章](/intro-to-storybook/react/ja/composite-component)で行ったのと同様に、デコレーターに頼ることができ、Storybook の中でモックストアを利用できます:
-
-```js:title=src/components/TaskList.stories.js
-import React from 'react';
+この問題を解決するために、さまざまなアプローチができます。しかし、このアプリは非常に単純なので、[前の章](/intro-to-storybook/react/ja/composite-component)で行ったのと同様にデコレーターに頼ることができ、Storybook の中でモックストアを利用できます。
+```jsx:title=src/components/TaskList.stories.jsx
import TaskList from './TaskList';
import * as TaskStories from './Task.stories';
@@ -183,7 +181,7 @@ import { Provider } from 'react-redux';
import { configureStore, createSlice } from '@reduxjs/toolkit';
-// A super-simple mock of the state of the store
+// 超シンプルなストアの状態のモック
export const MockedState = {
tasks: [
{ ...TaskStories.Default.args.task, id: '1', title: 'Task 1' },
@@ -197,7 +195,7 @@ export const MockedState = {
error: null,
};
-// A super-simple mock of a redux store
+// 超シンプルなreduxストアのモック
const Mockstore = ({ taskboxState, children }) => (
(
export default {
component: TaskList,
title: 'TaskList',
- decorators: [(story) => {story()}
],
+ decorators: [(story) => {story()}
],
+ tags: ['autodocs'],
excludeStories: /.*MockedState$/,
};
-const Template = () => ;
-
-export const Default = Template.bind({});
-Default.decorators = [
- (story) => {story()},
-];
+export const Default = {
+ decorators: [
+ (story) => {story()},
+ ],
+};
-export const WithPinnedTasks = Template.bind({});
-WithPinnedTasks.decorators = [
- (story) => {
- const pinnedtasks = [
- ...MockedState.tasks.slice(0, 5),
- { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
- ];
+export const WithPinnedTasks = {
+ decorators: [
+ (story) => {
+ const pinnedtasks = [
+ ...MockedState.tasks.slice(0, 5),
+ { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
+ ];
+
+ return (
+
+ {story()}
+
+ );
+ },
+ ],
+};
- return (
+export const Loading = {
+ decorators: [
+ (story) => (
{story()}
- );
- },
-];
-
-export const Loading = Template.bind({});
-Loading.decorators = [
- (story) => (
-
- {story()}
-
- ),
-];
+ ),
+ ],
+};
-export const Empty = Template.bind({});
-Empty.decorators = [
- (story) => (
-
- {story()}
-
- ),
-];
+export const Empty = {
+ decorators: [
+ (story) => (
+
+ {story()}
+
+ ),
+ ],
+};
```
-💡
excludeStories
は Storybook の設定のフィールドで、モックされた状態がストーリーとして扱われるのを防ぐためのものです。このフィールドについては
Storybook documentation で詳しく説明されています。
+💡
excludeStories
は Storybook の設定のフィールドで、モックされた状態がストーリーとして扱われるのを防ぐためのものです。このフィールドについては
ドキュメント で詳しく説明されています。
-💡 この変更により、全てのテストはアップデートが必要になります。-u
フラグをつけてテストを再実行し、アップデートしてください。 Git へのコミットを忘れずに行ってください!
+💡 Git へのコミットを忘れずに行ってください!
成功です! Storybook が動作し、接続されたコンポーネントにデータを渡す方法を確認することができました。次の章では、ここで学んだことを画面に適用してみましょう。
From ec0ce21ebeaad3a732197907b81da7b930a3eabf Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Thu, 16 May 2024 20:54:47 +0900
Subject: [PATCH 05/14] Update screen.md
---
content/intro-to-storybook/react/ja/screen.md | 265 ++++++++++--------
1 file changed, 147 insertions(+), 118 deletions(-)
diff --git a/content/intro-to-storybook/react/ja/screen.md b/content/intro-to-storybook/react/ja/screen.md
index 67cd29a67..3d5bd371a 100644
--- a/content/intro-to-storybook/react/ja/screen.md
+++ b/content/intro-to-storybook/react/ja/screen.md
@@ -5,7 +5,7 @@ description: 'コンポーネントをまとめて画面を作りましょう'
commit: '2275632'
---
-今までボトムアップ (小さく始めてから複雑性を追加していく) で UI の作成に集中してきました。ボトムアップで作業することで、Storybook で遊びながら、それぞれのコンポーネントを切り離された環境で、それぞれに必要なデータを考えながら開発することができました。サーバーを立ち上げたり、画面を作ったりする必要は全くありませんでした!
+今までボトムアップ (小規模な状態から複雑さを追加していく) で UI の作成に集中してきました。ボトムアップで作業することで、Storybook で遊びながら、それぞれのコンポーネントを切り離された環境で、それぞれに必要なデータを考えながら開発することができました。サーバーを立ち上げたり、画面を作ったりする必要はまったくありませんでした!
この章では Storybook を使用して、コンポーネントを組み合わせて画面を作り、完成度を高めていきます。
@@ -13,11 +13,11 @@ commit: '2275632'
このアプリケーションはとても単純なので、作る画面は些細なものです。リモート API からデータを取得し、(Redux から自分でデータを取得する) `TaskList` をラップして、Redux からの `error` フィールドを追加するだけです。
-まず、リモート API に接続して様々な状態 (すなわち、`error`、`succeeded`) をアプリケーションで扱えるようにするために、Redux ストア (`src/lib/store.js` 内) をアップデートするところから始めましょう:
+まず、リモート API に接続してさまざまな状態 (すなわち、`error`、`succeeded`) をアプリケーションで扱えるようにするために、Redux ストア (`src/lib/store.js` 内) をアップデートするところから始めましょう。
```diff:title=src/lib/store.js
-/* A simple redux store/actions/reducer implementation.
- * A true app would be more complex and separated into different files.
+/* シンプルなreduxのストア/アクション/リデューサーの実装です。
+ * 本当のアプリケーションはもっと複雑で、異なるファイルに分けられます。
*/
import {
configureStore,
@@ -26,19 +26,19 @@ import {
} from '@reduxjs/toolkit';
/*
- * The initial state of our store when the app loads.
- * Usually, you would fetch this from a server. Let's not worry about that now
+ * アプリケーションのロード時のストアの初期状態です。
+ * 通常、サーバーから取得しますが、今回は気にしないでください(ファイルに直書きしています)。
*/
const TaskBoxData = {
tasks: [],
- status: "idle",
+ status: 'idle',
error: null,
};
/*
- * Creates an asyncThunk to fetch tasks from a remote endpoint.
- * You can read more about Redux Toolkit's thunks in the docs:
+ * AsyncThunkを使ってリモートエンドポイントからタスクを取得します。
+ * Redux Toolkitのthunkについて詳しくはドキュメントを参照してください:
* https://redux-toolkit.js.org/api/createAsyncThunk
*/
+ export const fetchTasks = createAsyncThunk('todos/fetchTodos', async () => {
@@ -55,8 +55,8 @@ const TaskBoxData = {
+ });
/*
- * The store is created here.
- * You can read more about Redux Toolkit's slices in the docs:
+ * ストアはここで作成されます。
+ * Redux Toolkitのスライスについて詳しくはドキュメントを参照してください:
* https://redux-toolkit.js.org/api/createSlice
*/
const TasksSlice = createSlice({
@@ -72,8 +72,8 @@ const TasksSlice = createSlice({
},
},
/*
- * Extends the reducer for the async actions
- * You can read more about it at https://redux-toolkit.js.org/api/createAsyncThunk
+ * 非同期アクション用のリデューサを追加します。
+ * 詳しくは https://redux-toolkit.js.org/api/createAsyncThunk を参照してください。
*/
+ extraReducers(builder) {
+ builder
@@ -96,12 +96,12 @@ const TasksSlice = createSlice({
+ },
});
-// The actions contained in the slice are exported for usage in our components
+// スライスに含まれるアクションはコンポーネントで使用するためにエクスポートされます
export const { updateTaskState } = TasksSlice.actions;
/*
- * Our app's store configuration goes here.
- * Read more about Redux's configureStore in the docs:
+ * アプリケーションのストアの設定はここにあります。
+ * ReduxのconfigureStoreについて詳しくはドキュメントを参照してください:
* https://redux-toolkit.js.org/api/configureStore
*/
const store = configureStore({
@@ -113,12 +113,15 @@ const store = configureStore({
export default store;
```
-リモート API エンドポイントからデータを取得するようにストアを更新し、アプリのさまざまな状態を処理できるように準備したので、`InboxScreen.js` を `src/components` ディレクトリに作成しましょう:
+リモート API エンドポイントからデータを取得するようにストアを更新し、アプリのさまざまな状態を処理できるように準備したので、`InboxScreen.jsx` を `src/components` ディレクトリに作成しましょう:
-```js:title=src/components/InboxScreen.js
+```jsx:title=src/components/InboxScreen.jsx
import React, { useEffect } from 'react';
+
import { useDispatch, useSelector } from 'react-redux';
+
import { fetchTasks } from '../lib/store';
+
import TaskList from './TaskList';
export default function InboxScreen() {
@@ -135,8 +138,8 @@ export default function InboxScreen() {
-
Oh no!
-
Something went wrong
+
Oh no!
+
Something went wrong
);
@@ -144,9 +147,7 @@ export default function InboxScreen() {
return (
@@ -156,9 +157,12 @@ export default function InboxScreen() {
さらに、`App` コンポーネントを `InboxScreen` を描画するように変更します (いずれはルーターにどの画面を表示するか決めてもらいますが、今は気にしないでください):
-```diff:title=src/App.js
-- import logo from './logo.svg';
-- import './App.css';
+```diff:title=src/App.jsx
+- import { useState } from 'react'
+- import reactLogo from './assets/react.svg'
+- import viteLogo from '/vite.svg'
+- import './App.css'
+
+ import './index.css';
+ import store from './lib/store';
@@ -166,22 +170,29 @@ export default function InboxScreen() {
+ import InboxScreen from './components/InboxScreen';
function App() {
+- const [count, setCount] = useState(0)
return (
-
+
+
@@ -193,11 +204,9 @@ export default App;
しかし、面白くなるのは Storybook でストーリーをレンダリングするときです。
-前回見たように、`TaskList` コンポーネントは現在 **接続された** コンポーネントで、タスクのレンダリングは Redux ストアに依存しています。`InboxScreen` も接続されたコンポーネントなので、同じように、ストーリーにストアを渡します。以下のように `InboxScreen.stories.js` でストーリーを設定します:
-
-```js:title=src/components/InboxScreen.stories.js
-import React from 'react';
+前回見たように、`TaskList` コンポーネントは現在 **接続された** コンポーネントで、タスクのレンダリングは Redux ストアに依存しています。`InboxScreen` も接続されたコンポーネントなので、同じように、ストーリーにストアを渡します。以下のように `InboxScreen.stories.jsx` でストーリーを設定します:
+```jsx:title=src/components/InboxScreen.stories.jsx
import InboxScreen from './InboxScreen';
import store from '../lib/store';
@@ -207,25 +216,26 @@ export default {
component: InboxScreen,
title: 'InboxScreen',
decorators: [(story) => {story()}],
+ tags: ['autodocs'],
};
-const Template = () => ;
+export const Default = {};
-export const Default = Template.bind({});
-export const Error = Template.bind({});
+export const Error = {};
+``` const Error = Template.bind({});
```
-私たちは `error` ストーリーですぐに問題を発見することができます。正しい状態が表示されず、タスクのリストが表示されます。この問題を回避する 1 つの方法は、前章で行ったように各状態に対してモックされたバージョンを提供することです。その代わりに、よく知られた API モッキングライブラリを Storybook アドオンと一緒に使用して、この問題を解決するのに役立てます。
+私たちは `error` ストーリーですぐに問題を発見できます。正しい状態が表示されず、タスクのリストが表示されます。この問題を回避する 1 つの方法は、前章で行ったように各状態に対してモックされたバージョンを提供することです。その代わりに、よく知られた API モッキングライブラリを Storybook アドオンと一緒に使用して、この問題を解決するのに役立てます。
-![壊れた Inbox 画面の状態](/intro-to-storybook/broken-inbox-error-state-optimized.png)
+![壊れた Inbox 画面の状態](/intro-to-storybook/broken-inbox-error-state-7-0-optimized.png)
## API をモックする
-今回のアプリケーションは単純で、リモート API 呼び出しにあまり依存しないので、[Mock Service Worker](https://mswjs.io/) と [Storybook's MSW addon](https://storybook.js.org/addons/msw-storybook-addon) を使用することにします。Mock Service Worker は、API モックライブラリです。Service Worker に依存してネットワークリクエストを捕捉し、モックデータをレスポンスします。
+今回のアプリケーションは単純で、リモート API 呼び出しにあまり依存しないので、[Mock Service Worker](https://mswjs.io/) と [Storybook MSW アドオン](https://storybook.js.org/addons/msw-storybook-addon) を使用することにします。Mock Service Worker は、API モックライブラリです。Service Worker に依存してネットワークリクエストを捕捉し、モックデータをレスポンスします。
-[Get started section](/intro-to-storybook/react/en/get-started) でアプリケーションをセットアップすると、両方のパッケージともインストールされます。あとは、それらを設定しストーリーを更新して使用するのみです。
+[初めの章](/intro-to-storybook/react/ja/get-started) でアプリケーションをセットアップしたときに、これらのパッケージはすでにインストールされています。あとは、それらを設定しストーリーを更新して使用するのみです。
-ターミナルで以下のコマンドを実行し、`public` フォルダの中にサービスワーカーを生成します。:
+ターミナルで以下のコマンドを実行し、`public` フォルダの中にサービスワーカーを生成します。
```shell
yarn init-msw
@@ -236,32 +246,33 @@ yarn init-msw
```diff:title=.storybook/preview.js
import '../src/index.css';
-+ // Registers the msw addon
-+ import { initialize, mswDecorator } from 'msw-storybook-addon';
++ // mswアドオンを登録
++ import { initialize, mswLoader } from 'msw-storybook-addon';
-+ // Initialize MSW
++ // MSWを初期化
+ initialize();
-+ // Provide the MSW addon decorator globally
-+ export const decorators = [mswDecorator];
-
//👇 Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI.
-export const parameters = {
- actions: { argTypesRegex: '^on[A-Z].*' },
- controls: {
- matchers: {
- color: /(background|color)$/i,
- date: /Date$/,
+/** @type { import('@storybook/react').Preview } */
+const preview = {
+ parameters: {
+ actions: { argTypesRegex: "^on[A-Z].*" },
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/,
+ },
},
},
++ loaders: [mswLoader],
};
-```
-最後に、`InboxScreen` のストーリーを更新し、リモート API 呼び出しをモックする [parameter](https://storybook.js.org/docs/react/writing-stories/parameters) を組み込みます:
+export default preview;
+```
-```diff:title=src/components/InboxScreen.stories.js
-import React from 'react';
+最後に、`InboxScreen` のストーリーを更新し、リモート API 呼び出しをモックする [parameter](https://storybook.js.org/docs/react/writing-stories/parameters) を組み込みます。
+```diff:title=src/components/InboxScreen.stories.jsx
import InboxScreen from './InboxScreen';
import store from '../lib/store';
+ import { rest } from 'msw';
@@ -272,12 +283,11 @@ export default {
component: InboxScreen,
title: 'InboxScreen',
decorators: [(story) => {story()}],
+ tags: ['autodocs'],
};
-const Template = () => ;
-
-export const Default = Template.bind({});
-+ Default.parameters = {
+export const Default = {
++ parameters: {
+ msw: {
+ handlers: [
+ rest.get(
@@ -288,10 +298,10 @@ export const Default = Template.bind({});
+ ),
+ ],
+ },
-+ };
-
-export const Error = Template.bind({});
-+ Error.parameters = {
++ },
+};
+export const Error = {
++ parameters: {
+ msw: {
+ handlers: [
+ rest.get(
@@ -302,7 +312,8 @@ export const Error = Template.bind({});
+ ),
+ ],
+ },
-+ };
++ },
+};
```
@@ -314,7 +325,7 @@ Storybook で `error` ストーリーが意図したように動作している
@@ -331,13 +342,11 @@ Storybook の [`play`](https://storybook.js.org/docs/react/writing-stories/play-
play 関数はタスクが更新されたときに UI に何が起こるかを検証するのに役立ちます。フレームワークに依存しない DOM API を使用しています。つまり、 play 関数を使って UI を操作し、人間の行動をシミュレートするストーリーを、フロントエンドのフレームワークに関係なく書くことができるのです。
-`@storybook/addon-interactions`は、一つ一つのステップごとに Storybook のテストを可視化するのに役立ちます。さらに、各インタラクションの一時停止、再開、巻き戻し、ステップ実行といった便利な UI の制御機能が備わっています。
+`@storybook/addon-interactions`は、ひとつひとつのステップごとに Storybook のテストを可視化するのに役立ちます。さらに、各インタラクションの一時停止、再開、巻き戻し、ステップ実行といった便利な UI の制御機能が備わっています。
-実際に動かしてみましょう!以下のようにして新しく作成された `InboxScreen` ストーリーを更新し、コンポーネント操作を追加してみましょう:
-
-```diff:title=src/components/InboxScreen.stories.js
-import React from 'react';
+実際に動かしてみましょう!以下のようにして新しく作成された `InboxScreen` ストーリーを更新し、コンポーネント操作を追加してみましょう。
+```diff:title=src/components/InboxScreen.stories.jsx
import InboxScreen from './InboxScreen';
import store from '../lib/store';
@@ -347,73 +356,93 @@ import { Provider } from 'react-redux';
+ import {
+ fireEvent,
-+ within,
+ waitFor,
++ within,
+ waitForElementToBeRemoved
-+ } from '@storybook/testing-library';
++ } from '@storybook/test';
export default {
component: InboxScreen,
title: 'InboxScreen',
decorators: [(story) =>
{story()}],
+ tags: ['autodocs'],
};
-const Template = () =>
;
-
-export const Default = Template.bind({});
-Default.parameters = {
- msw: {
- handlers: [
- rest.get(
- 'https://jsonplaceholder.typicode.com/todos?userId=1',
- (req, res, ctx) => {
- return res(ctx.json(MockedState.tasks));
- }
- ),
- ],
+export const Default = {
+ parameters: {
+ msw: {
+ handlers: [
+ rest.get(
+ 'https://jsonplaceholder.typicode.com/todos?userId=1',
+ (req, res, ctx) => {
+ return res(ctx.json(MockedState.tasks));
+ }
+ ),
+ ],
+ },
},
-};
-
-+ Default.play = async ({ canvasElement }) => {
++ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
-+ // Waits for the component to transition from the loading state
++ // コンポーネントのローディング状態からの遷移を待機
+ await waitForElementToBeRemoved(await canvas.findByTestId('loading'));
-+ // Waits for the component to be updated based on the store
++ // ストアに基づいたコンポーネントの更新を待機
+ await waitFor(async () => {
-+ // Simulates pinning the first task
++ // 最初のタスクのピン止めをシミュレート
+ await fireEvent.click(canvas.getByLabelText('pinTask-1'));
-+ // Simulates pinning the third task
++ // 3つ目のタスクのピン止めをシミュレート
+ await fireEvent.click(canvas.getByLabelText('pinTask-3'));
+ });
-+ };
++ },
+};
+export const Error = {
+ parameters: {
+ msw: {
+ handlers: [
+ rest.get(
+ 'https://jsonplaceholder.typicode.com/todos?userId=1',
+ (req, res, ctx) => {
+ return res(ctx.status(403));
+ }
+ ),
+ ],
+ },
+ },
+};
```
-新しく作成したストーリーを確認します。`Interactions` パネルをクリックすると、ストーリーの play 関数内のインタラクションのリストが表示されます。
+
+
+💡 The `@storybook/test` パッケージは `@storybook/jest`と`@storybook/testing-library`を置き換えるものです。
+より小さなバンドルサイズと、VitestパッケージをベースにしたよりわかりやすいAPIを提供します。
+
+
+
+`Default`ストーリーを確認します。`Interactions` パネルをクリックすると、ストーリーの play 関数内のインタラクションのリストが表示されます。
-### テスト自動化
+### test runnerによるテストの自動化
-play 関数を利用して、UI を操作し、タスクを更新した場合の反応を素早く確認することができます。これによって、余計な手間をかけずに UI の一貫性を保つことができます。
+play 関数を利用して、UI を操作し、タスクを更新した場合の反応を素早く確認できます。これによって、余計な手間をかけずに UI の一貫性を保つことができます。
-しかし、Storybook をよく見ると、ストーリーを見るときだけインタラクションテストが実行されることがわかります。そのため、変更時に各ストーリーを全てチェックしなければなりません。これは自動化できないのでしょうか?
+しかし、Storybook をよく見ると、ストーリーを見るときだけインタラクションテストが実行されることがわかります。そのため、変更時に各ストーリーをすべてチェックしなければなりません。これは自動化できないのでしょうか?
-可能です!Storybook の[テストランナー](https://storybook.js.org/docs/react/writing-tests/test-runner)は可能にしてくれます。それは [Playwright](https://playwright.dev/) によって実現されたスタンドアロンなパッケージで、全てのインタラクションテストを実行し、壊れたストーリーを検知してくれます。
+結論から言うと、それは可能です!Storybook の[テストランナー](https://storybook.js.org/docs/react/writing-tests/test-runner)は [Playwright](https://playwright.dev/) によって実現されたスタンドアロンなパッケージで、すべのインタラクションテストを実行し、壊れたストーリーを検知してくれます。
-それではどのように動くのかみてみましょう!次のコマンドでインストールして走らせます:
+それではどのように動くのかみてみましょう!次のコマンドでインストールします。
```bash
yarn add --dev @storybook/test-runner
```
-次に、 `package.json` の `scripts` をアップデートし、新しいテストタスクを追加してください:
+次に、 `package.json` の `scripts` を更新し、新しいテストタスクを追加してください。
-```json
+```json:clipboard=false
{
"scripts": {
"test-storybook": "test-storybook"
@@ -421,7 +450,7 @@ yarn add --dev @storybook/test-runner
}
```
-最後に、Storybook を起動し、新しいターミナルで以下のコマンドを実行してください:
+最後に、Storybook を起動し、新しいターミナルで以下のコマンドを実行してください。
```bash
yarn test-storybook --watch
@@ -435,11 +464,11 @@ yarn test-storybook --watch
![Storybook test runner successfully runs all tests](/intro-to-storybook/storybook-test-runner-execution.png)
-成功です!これで、全てのストーリーがエラーなくレンダリングされ、全てのテストが自動的に通過するかどうか検証するためのツールができました。さらに、テストが失敗した場合、失敗したストーリーをブラウザで開くリンクを提供してくれます。
+成功です!これで、すべてのストーリーがエラーなくレンダリングされ、すべてのテストが自動的に通過するかどうか検証するためのツールができました。さらに、テストが失敗した場合、失敗したストーリーをブラウザで開くリンクを提供してくれます。
## コンポーネント駆動開発
-まず、一番下の `Task` から始めて、`TaskList` を作り、画面全体の UI が出来ました。`InboxScreen` では繋がれたコンポーネントを含み、一緒にストーリーも作成しました。
+まず、一番下の `Task` から始めて、`TaskList` を作り、画面全体の UI ができました。`InboxScreen` では繋がれたコンポーネントを含み、一緒にストーリーも作成しました。
-[**コンポーネント駆動開発**](https://www.componentdriven.org/) (CDD) はコンポーネント階層を上がるごとに少しずつ複雑性を拡張していきます。利点としては、開発プロセスに集中できること、UI の組み合わせの網羅性を向上できること、が挙げられます。要するに、CDD によって、高品質で複雑な UI を作ることができます。
+[**コンポーネント駆動開発**](https://www.componentdriven.org/) (CDD) はコンポーネント階層を上がるごとに少しずつ複雑性を拡張します。利点としては、開発プロセスに集中できること、UI の組み合わせの網羅性を向上できること、が挙げられます。要するに、CDD によって、高品質で複雑な UI を作ることができます。
-まだ終わりではありません。UI を作成しても仕事は終わりません。長期間にわたり耐久性を維持できるようにしなければなりません。
+まだ終わりではありません。UI を作成しても作業は終わりません。長期間にわたり耐久性を維持できるようにしなければなりません。
💡 Git へのコミットを忘れずに行ってください!
From 3811f28a92800f87585a1a9f555a6aa17ddd7632 Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Thu, 16 May 2024 21:04:44 +0900
Subject: [PATCH 06/14] Update deploy.md
---
content/intro-to-storybook/react/ja/deploy.md | 58 ++++++++++---------
1 file changed, 30 insertions(+), 28 deletions(-)
diff --git a/content/intro-to-storybook/react/ja/deploy.md b/content/intro-to-storybook/react/ja/deploy.md
index 94ba7cf97..1f2fcb4d7 100644
--- a/content/intro-to-storybook/react/ja/deploy.md
+++ b/content/intro-to-storybook/react/ja/deploy.md
@@ -11,27 +11,27 @@ commit: '59da1ac'
Storybook をデプロイするには、まず静的サイトとしてエクスポートします。この機能はすでに組み込まれて、使える状態となっているので、設定について気にする必要はありません。
-`yarn build-storybook` を実行すると、`storybook-static` ディレクトリーに Storybook が静的サイトとして出力されますので、静的サイトのホスティングサービスのデプロイ出来ます。
+`yarn build-storybook` を実行すると、`storybook-static` ディレクトリに Storybook が静的サイトとして出力されますので、静的サイトのホスティングサービスにデプロイできます。
-## Storybook を発行する
+## Storybook を公開する
-このチュートリアルでは、Storybook のメンテナーが作成した、無料のホスティングサービスである
Chromatic を使用します。Chromatic を使えば、クラウド上に Storybook を安全に、デプロイしホストすることができます。
+このチュートリアルでは、Storybook のメンテナーが作成した、無料のホスティングサービスである
Chromatic を使用します。Chromatic を使えば、クラウド上に Storybook を安全にデプロイし、またホストできます。
### GitHub にリポジトリーを作成する
-デプロイの前に、リモートのバージョン管理サービスへローカルのコードを同期しなければなりません。[はじめにの章](/intro-to-storybook/react/ja/get-started/)で Create React App (CRA) でプロジェクトを初期化した際に、ローカルのリポジトリーはすでに作成されています。また、この段階でリモートリポジトリーにプッシュできるコミットがあるはずです。
+デプロイの前に、リモートのバージョン管理サービスへローカルのコードを同期しなければなりません。[はじめの章](/intro-to-storybook/react/ja/get-started/)でプロジェクトを初期化した際に、ローカルのリポジトリーはすでに作成されています。この段階に来れば、リモートリポジトリーにプッシュできるコミットがあるはずです。
-[ここから](https://github.com/new) GitHub にアクセスし、リポジトリーを作りましょう。リポジトリーの名前はローカルと同じく「taskbox」とします。
+[ここから](https://github.com/new) GitHub にアクセスし、リポジトリを作りましょう。リポジトリの名前はローカルと同じく「taskbox」とします。
![GitHub のセットアップ](/intro-to-storybook/github-create-taskbox.png)
-新しいリポジトリーを作ったら origin の URL をコピーして、次のコマンドを実行し、ローカルの Git プロジェクトにリモートを追加します:
+新しいリポジトリを作ったら origin の URL をコピーして、次のコマンドを実行し、ローカルの Git リポジトリを GitHub のリモートリポジトリーに追加します。
```shell
-git remote add origin https://github.com/
/taskbox.git
+git remote add origin https://github.com//taskbox.git
```
-最後にローカルリポジトリーを GitHub のリモートリポジトリーにプッシュします:
+最後にローカルリポジトリを GitHub のリモートリポジトリにプッシュします:
```shell
git push -u origin main
@@ -45,9 +45,9 @@ git push -u origin main
yarn add -D chromatic
```
-パッケージをインストールしたら、GitHub のアカウントを使用して [Chromatic にログイン](https://www.chromatic.com/start/?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook)します。(Chromatic は一部のアクセス許可を要求します。) 「taskbox」という名前でプロジェクトを作成し、GitHub のリポジトリーと同期させます。
+パッケージをインストールしたら、GitHub のアカウントを使用して [Chromatic にログイン](https://www.chromatic.com/start/?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook)します。(Chromatic は一部のアクセス許可を要求します。)「taskbox」という名前でプロジェクトを作成し、GitHub のリポジトリと同期させます。
-ログインしたら `Choose from GitHub` をクリックし、リポジトリーを選択します。
+ログインしたら `Choose GitHub repo` をクリックし、リポジトリを選択します。
-![Storybook test runner successfully runs all tests](/intro-to-storybook/storybook-test-runner-execution.png)
+![Storybook のテストランナーがすべてのテストの実行を成功させる様子](/intro-to-storybook/storybook-test-runner-execution.png)
成功です!これで、すべてのストーリーがエラーなくレンダリングされ、すべてのテストが自動的に通過するかどうか検証するためのツールができました。さらに、テストが失敗した場合、失敗したストーリーをブラウザで開くリンクを提供してくれます。
diff --git a/content/intro-to-storybook/react/ja/simple-component.md b/content/intro-to-storybook/react/ja/simple-component.md
index ff98d65c5..3dad1b504 100644
--- a/content/intro-to-storybook/react/ja/simple-component.md
+++ b/content/intro-to-storybook/react/ja/simple-component.md
@@ -22,7 +22,7 @@ commit: '9b36e1a'
まずは、タスクのコンポーネントと、対応するストーリーファイル `src/components/Task.jsx` と `src/components/Task.stories.jsx` を作成しましょう。
-`Task` の基本的な実装から始めます。`Task` は上述したプロパティと、タスクに対して実行できる 2 つの (リスト間を移動させる) アクションを引数として取ります:
+`Task` の基本的な実装から始めます。`Task` は上述したプロパティと、タスクに対して実行できる 2 つの (リスト間を移動させる) アクションを引数として取ります。
```js:title=src/components/Task.jsx
import React from 'react';
@@ -40,7 +40,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT
上のコードは Todo アプリケーションの HTML を基にした `Task` の簡単なマークアップです。
-下のコードは `Task` に対する 3 つのテスト用の状態をストーリーファイルに書いています:
+下のコードは `Task` に対する 3 つのテスト用の状態をストーリーファイルに書くものです。
```js:title=src/components/Task.stories.jsx
import Task from './Task';
@@ -103,7 +103,7 @@ Arguments (略して [`args`](https://storybook.js.org/docs/react/writing-storie
作成したストーリーを認識させたり、CSS ファイル (`src/index.css`にあります) をStorybook上で使用できるようにするため、Storybook の設定をいくつか変更する必要があります。
-まず、設定ファイル (`.storybook/main.js`) を以下のように変更してください:
+まず、設定ファイル (`.storybook/main.js`) を以下のように変更してください。
```diff:title=.storybook/main.js
/** @type { import('@storybook/react-vite').StorybookConfig } */
@@ -127,12 +127,12 @@ const config = {
export default config;
```
-上記の変更が完了したら、`.storybook` フォルダー内の `preview.js` を、以下のように変更してください:
+上記の変更が完了したら、`.storybook` フォルダー内の `preview.js` を、以下のように変更してください。
```diff:title=.storybook/preview.js
+ import '../src/index.css';
-//👇 Storybookのアクション(onArchiveTaskとonPinTask)をUIに記録するように設定します。
+//👇 Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI.
/** @type { import('@storybook/react').Preview } */
const preview = {
parameters: {
@@ -166,7 +166,7 @@ Storybook のサーバーを再起動すると、タスクの 3 つの状態の
ここまでで、Storybook のセットアップが完了し、スタイルをインポートし、テストケースを作りました。早速、デザインに合わせてコンポーネントの HTML を実装していきましょう。
-今のところコンポーネントは簡素な状態です。まずはデザインを実現するために最低限必要なコードを書いてみましょう:
+今のところコンポーネントは簡素な状態です。まずはデザインを実現するために最低限必要なコードを書いてみましょう。
```jsx:title=src/components/Task.jsx
import React from 'react';
@@ -218,7 +218,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT
}
```
-追加したマークアップとインポートした CSS により以下のような UI ができます:
+追加したマークアップとインポートした CSS により以下のような UI ができます。
-### test runnerによるテストの自動化
+### test runner によるテストの自動化
play 関数を利用して、UI を操作し、タスクを更新した場合の反応を素早く確認できます。これによって、余計な手間をかけずに UI の一貫性を保つことができます。
From 17b2af48743d9a47365f80835b3a5babe822e472 Mon Sep 17 00:00:00 2001
From: UHAsikakutou <91722200+UHAsikakutou@users.noreply.github.com>
Date: Sun, 21 Jul 2024 12:43:41 +0900
Subject: [PATCH 14/14] Fix: update ` actions/checkout` to v4
---
content/intro-to-storybook/react/ja/deploy.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content/intro-to-storybook/react/ja/deploy.md b/content/intro-to-storybook/react/ja/deploy.md
index 2c05b1a30..b0712f465 100644
--- a/content/intro-to-storybook/react/ja/deploy.md
+++ b/content/intro-to-storybook/react/ja/deploy.md
@@ -94,7 +94,7 @@ jobs:
runs-on: ubuntu-latest
# Job steps
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
- run: yarn