Redux Style Guide
日本語訳ではなくasRagi.iconによる解釈
◆必須
store.jsのように独立したファイルで管理する. ◆強く推奨
例
/src
index.tsx: Entry point file that renders the React component tree
/app
store.ts: store setup
rootReducer.ts: root reducer (optional)
App.tsx: root React component
/common: hooks, generic components, utils, etc
/features: contains all "feature folders"
/todos: a single feature folder
todosSlice.ts: Redux reducer logic and associated actions
Todos.tsx: a React component
状態の更新に関わるロジックがどこに書かれているか一目瞭然となる. return action.payloadやreturn {...state, ...action.payload}のようにスプレッド構文を利用すると,更新後の状態の形状が渡されてきたactionやstateに依存してしまう. code:example.js
const initialState = {
firstName: null,
lastName: null,
age: null,
};
export default usersReducer = (state = initialState, action) {
switch(action.type) {
case "users/userLoggedIn": {
return action.payload;
}
default: return state;
}
}
// usersReducerに以下のdispatchが飛んでくると破滅する
dispatch({
type: 'users/userLoggedIn',
payload: {
id: 42,
text: 'Buy milk'
}
});
{userReducer: {}, postsReducer: {}}ではなく,{users: {}, posts: {}}という形でstateが保存されるべきである. 例
fetchUserReducerは以下の状態を取ると定める. "idle","loading","success","failure"
code:state.js
const initialUserState = {
status: 'idle',
user: null,
error: null
};
code:state.js
import {
FETCH_USER,
// ...
} from './actions'
const IDLE_STATUS = 'idle';
const LOADING_STATUS = 'loading';
const SUCCESS_STATUS = 'success';
const FAILURE_STATUS = 'failure';
const fetchIdleUserReducer = (state, action) => {
// state.status is "idle"
switch (action.type) {
case FETCH_USER:
return {
...state,
status: LOADING_STATUS
}
}
default:
return state;
}
}
// ... other reducers
const fetchUserReducer = (state, action) => {
switch (state.status) {
case IDLE_STATUS:
return fetchIdleUserReducer(state, action);
case LOADING_STATUS:
return fetchLoadingUserReducer(state, action);
case SUCCESS_STATUS:
return fetchSuccessUserReducer(state, action);
case FAILURE_STATUS:
return fetchFailureUserReducer(state, action);
default:
// this should never be reached
return state;
}
}
code:event.js
// Action described by Event
const eventObject = { type: "food/orderAdded", payload: { pizza: 1, coke: 1 } };
// Action described like setter
const pizza = {
type: "orders/setPizzasOrdered",
// Clients should know current state.
payload: { amount: getState().orders.pizza + 1 }
};
<UserList>で全ユーザのデータを取得して一覧表示するのではなく,<UserListItem userId={userId}>がそれぞれStoreに接続しユーザのデータを取得する. とはいえ,細かすぎるのも良くないのでうまくバランスする.
データ型の変換が複雑になってしまうリスクが低減する. ◆推奨
要約すると以下の通り
デフォルトで用いることが推奨されている.
selectVisibleTodosみたいに命名する. 参考