はじめに
枠が空いていましたので、Advent Calendarに参加させていただきました。
10月からReactの学習を始めた新参者です。
間違っているところなどあればご指摘頂けると幸いです。
React Reduxを学ぼうと思った時に Basic Tutorial | React Redux にあるTodoAppをみる方も多いと思います。
私はReactの学習を くるみ割り書房 ft. React - BOOTH さんから出ているりあクト!シリーズで勉強しているのですが、改めてBasic TutorialのTodoAppを見るとこれはこのまま実務のコードとして参考に出来ないなと思いました。
例えば、function TodoApp()
など関数でなく、アロー関数で書くなど。
これからReactでプロジェクトを進めていく時はおそらくどこもアロー関数になると思います。
これからReactを学ぶ上で最小限の小さいアプリを作っておいて見返すのは大事だと思いますので、せっかくならReact Redux Basic TutorialのTodoAppを書き直そうと思いました。
記事では、下記リポジトリの補足コメントを書いてるところが大きいです。
https://github.com/nori1994/todo-app-react
(追記)
2021/5にRedux公式ドキュメントが更新されてます。
ReduxのチュートリアルがRedux Toolkitを使って綺麗になっているのでこちらを見ればよさそうです。
https://redux.js.org/tutorials/quick-start
Reduxの学習リソースも増えてます。
https://redux.js.org/introduction/learning-resources#learning-resources
他にもFAQも増えたような気がします
TodoApp
React Redux Basic TutorialにあるTodoAppを書き直してみた pic.twitter.com/HZ0RZilcry
— nori (@nori0__) December 6, 2020
Basic Tutorial | React Redux の全ての機能が揃っているわけでなく、最低限React Reduxとは?が分かる範囲で書いています。
そして、りあクト!の11-redux/04-toolkit/src/features/todo.ts
で紹介されているSliceを実際に使うとどうなるのかを検証したかったためコードの参考引用しているところがあります。
Slice
Sliceは、Action と Reducerをまとめて定義できるためすっきり記述できます。
Action と Reducerとは?という方は下記にざっくりと書いたので参考になれば嬉しいです。
Action
Actionは、イベント、例えばStateをどう変化させるかを定義します。
ActionType(文字列)からActionCreatorと呼ばれる Actionを作る関数を生成します。
Reducer
Reducerは、以下のように古いStateとActionから新しいStateを取得するようになっています。
type Reducer<S, A> = (state: S, action: A) => S
Three Principles | Redux
Actionは、Dispatcherを介してReducterに渡されます。
createSlice
を使うとActionTypeの定義とActionCreator、Reducerをまとめて定義できます。
今回のTodoAppにはTodoを管理する、表示内容をフィルターするの大きく2つの機能があると考えたので、それぞれSliceを生成して、combineReducers
で1つのReducerにしました。
createSlice | Redux Toolkit
combineReducers | Redux
例えば表示内容をフィルターする場合は、以下のようにAction と Reducerを定義しました。
export const visibilityFilterSlice = createSlice({
name: 'visibilityFilter',
initialState: {
visibilityFilter: VISIBILITY_FILTER.INCOMPLETE,
} as VisibilityFilterState,
reducers: {
changed: (state, action: PayloadAction<VISIBILTY_FILTER_TYPE>) => {
const changedValue = action.payload;
state.visibilityFilter = changedValue;
},
},
});
Store
Storeは、アプリでの状態Stateを保管するためのものです。
configureStore
でStoreを生成しています。
Stateの変化を履歴で表示してくれるデバックツールRedux DevTools extension がデフォルトでONになっているなど設定が優秀なので、configureStore
でStoreを作っています。
configureStore
などに含まれている内容は以下を参照。
Redux Toolkit: Overview | Redux
const rootReducer = combineReducers({
todo: todoSlice.reducer,
visibilityFilter: visibilityFilterSlice.reducer,
});
const store = configureStore({ reducer: rootReducer });
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);
Dispath
実際にStateを変更するにはDispatcherを介してReducterにActionが渡されることで変更されます。
const VisibilityFilters: FC = () => {
const dispatch = useDispatch();
const { changed } = visibilityFilterSlice.actions;
const visibilityFilterState = useSelector(
(state: RootState) => state.visibilityFilter,
);
return (
<div>
{Object.entries(VISIBILITY_FILTER).map(([_, currentFilter]) => {
return (
<text
key={`visibility-filter-${currentFilter}`}
className={`filter ' + ${
currentFilter === visibilityFilterState.visibilityFilter
? 'filter--active'
: ''
}`}
onClick={() => {
dispatch(changed(currentFilter as VISIBILTY_FILTER_TYPE));
}}
>
{currentFilter}
</text>
);
})}
</div>
);
};
まとめ
この小規模単位のアプリを手元に持っておけばこれどうなっているんだっけとなった時に振り返りやすくなったと感じています。
あと、くるみ割り書房 ft. React - BOOTHさんで出ている本は旧版を除いて全て購入しました。TodoAppも多大に影響を受けています。とてもおすすめです。