Reducerをオブジェクト(Object)で作りたい
ReactのフックAPIのリファレンスを見ると、以下のようにswitchを使ってReducerを定義している。
しかし、私はswitchがあまり好きではないので、オブジェクトで書くようにしている。
example.js
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
引用: フックAPIリファレンス(https://ja.reactjs.org/docs/hooks-reference.html#usereducer)
# createReducer関数をつくる
以下のようにReducerを書けるようにcreateReducerという関数を作った。
```js
{
[アクションタイプ1]: (state, action) => ({変更後のステート}),
[アクションタイプ2]: (state, action) => ({変更後のステート}),
...
}
createReducer.js
export const createReducer = (initialState={}, handlers={}) =>
(state = initialState, action) =>
handlers[action.type] && handlers[action.type]({...state}, action) || {...state}
説明は割愛するが、これを利用することで、前述のフックAPIリファレンスのサンプルコードを以下のように書くことができる。
example.js
const initialState = {count: 0};
const reducer = createReducer(initialState, {
['increment']: state => ({...state, count: state.count + 1}),
['decrement']: state => ({...state, count: state.count - 1})
}), initialState)
また、 payloadがある場合には、以下のように書くことができる。
example.js
const reducer = createReducer(initialState, {
[UPDATE_SUGGESTION_ITEMS]: (state, {payload}) => ({...state, suggestionItems: payload}),
[FETCH_POSTS]: (state, {payload}) => ({...state, tmpResult: payload}),
[FETCH_POST_DETAIL]: (state, {payload}) => ({...state, post: payload}),
}), initialState)