109 lines
3.8 KiB
Markdown
109 lines
3.8 KiB
Markdown
---
|
|
id: 5a24c314108439a4d4036150
|
|
title: ストアでアクションを処理する
|
|
challengeType: 6
|
|
forumTopicId: 301444
|
|
dashedName: handle-an-action-in-the-store
|
|
---
|
|
|
|
# --description--
|
|
|
|
アクションが作成されてディスパッチされた後、Redux ストアでは、そのアクションに対してどう応答するかを知る必要があります。 その役割を担うのが `reducer` (リデューサー) 関数です。 Redux のリデューサーは、アクションに応じて行われる state の変更を担います。 `reducer` は、引数として `state` と `action` を受け取り、常に新しい `state` を返します。 ここで重要なのは、これがレデューサーの**唯一の**役割であると理解することです。 副次的な処理はまったくありません。API のエンドポイントを呼び出すこともなく、驚くようなことも隠されていません。 レデューサーは、state と action を受け取って新しい state を返すだけの純粋な関数です。
|
|
|
|
Redux のもう一つの重要な原則は「`state` は読み取り専用である」ことです。 言い換えれば、`reducer` 関数は**常に** `state` の新しいコピーを返す必要があり、state を直接変更することは決して許されません。 Redux では状態の不変性を強制してはいませんが、レデューサー関数のコードではプログラマーが状態の不変性を強制する必要があります。 これについてはこのあとのチャレンジで練習します。
|
|
|
|
# --instructions--
|
|
|
|
コードエディターに、以前に紹介した例と、`reducer` 関数の冒頭部分があります。 `reducer` 関数の本体を入力して、タイプ `'LOGIN'` のアクションを受け取った場合に `login` が `true` に設定された state オブジェクトを返すようにしてください。 それ以外の場合は、現在の `state` を返してください。 現在の `state` とディスパッチされた `action` がレデューサーに渡されるため、`action.type` を使用してアクションタイプに直接アクセスすることができます。
|
|
|
|
# --hints--
|
|
|
|
関数 `loginAction` の呼び出しで、type プロパティが文字列 `LOGIN` に設定されたオブジェクトを返します。
|
|
|
|
```js
|
|
assert(loginAction().type === 'LOGIN');
|
|
```
|
|
|
|
オブジェクトのプロパティ `login` を `false` に設定してストアを初期化します。
|
|
|
|
```js
|
|
assert(store.getState().login === false);
|
|
```
|
|
|
|
`loginAction` のディスパッチで、ストアの state の `login` プロパティを `true` に更新します。
|
|
|
|
```js
|
|
assert(
|
|
(function () {
|
|
const initialState = store.getState();
|
|
store.dispatch(loginAction());
|
|
const afterState = store.getState();
|
|
return initialState.login === false && afterState.login === true;
|
|
})()
|
|
);
|
|
```
|
|
|
|
アクションがタイプ `LOGIN` でない場合、ストアは現在の state を返します。
|
|
|
|
```js
|
|
assert(
|
|
(function () {
|
|
store.dispatch({ type: '__TEST__ACTION__' });
|
|
let afterTest = store.getState();
|
|
return typeof afterTest === 'object' && afterTest.hasOwnProperty('login');
|
|
})()
|
|
);
|
|
```
|
|
|
|
# --seed--
|
|
|
|
## --seed-contents--
|
|
|
|
```js
|
|
const defaultState = {
|
|
login: false
|
|
};
|
|
|
|
const reducer = (state = defaultState, action) => {
|
|
// Change code below this line
|
|
|
|
// Change code above this line
|
|
};
|
|
|
|
const store = Redux.createStore(reducer);
|
|
|
|
const loginAction = () => {
|
|
return {
|
|
type: 'LOGIN'
|
|
}
|
|
};
|
|
```
|
|
|
|
# --solutions--
|
|
|
|
```js
|
|
const defaultState = {
|
|
login: false
|
|
};
|
|
|
|
const reducer = (state = defaultState, action) => {
|
|
|
|
if (action.type === 'LOGIN') {
|
|
return {login: true}
|
|
}
|
|
|
|
else {
|
|
return state
|
|
}
|
|
|
|
};
|
|
|
|
const store = Redux.createStore(reducer);
|
|
|
|
const loginAction = () => {
|
|
return {
|
|
type: 'LOGIN'
|
|
}
|
|
};
|
|
```
|