こんにちは。kaoruです。
前回まで状態変更をuseState()で行ってきましたが、今回はuseReducer()を使うように書き換えました。
【前回】React Testing Libraryでテスト実装 (Wheather-app実装 5)
useReducerを使う
useReducerって?
React Hookの一種です。
アプリの状態(state)と状態変更の一元化(reducer)を一括で扱えるようにします。
「Reducerって何やねん?」はここでは詳しく扱いません。
なぜuseReducer()を使う
単純な状態変更と再レンダリングだけであればuseStateでOKです。
複数の状態による組み合わせや一括変更など「複雑なロジック」にはuseReducerが適しているようです。
前回まで2つの状態をuseStateで管理/変更していました。
- 天気予報情報の有無
- 週間天気の表示/非表示
ボタン押下で上記2つを両方変更しており、useState()で変更した時点で一度再レンダリングされます。
つまり、一回のボタン押下で再レンダリングが2回起きてしまっています。
useReducer()を使うことで一括変更して再レンダリングを1回にします。
さらに処理や状態が増えたとしてもreducer処理を拡張していけばよくなります。
useState() から useReducer() へ書き換える
useReducerの要素を追加
initialState
stateの初期値です。
action
Reducerの変更処理対象(action.type)とパラメータ(action.xxx)の定義
reducer
action.typeから判断してstateを変更します。
stateはイミュータブル(直接変更できない)なので、Object.assign()で新しいstateで置き換えるようにします。
useReducer()の定義
const [state, dispatch] = React.useReducer(reducer, initialState)
のように書きます。
dispatchによるstateの変更
dispatch(アクションタイプ , パラメータ)
のように書きます。
実装時の手間取りポイント
TypeScript依存エラー
create-react-app error: import type * as PrettyFormat from ‘./types’
TypeScript を3.8.0に上げれば良いみたいです。(元は3.7.2)
yarn upgrade [email protected] したら、version選択が出たので3.8.1-rcにしました。
RCとは出荷候補(release candidate)のことで、本リリース直前のものみたいですね。
リネーム後のキャッシュエラー
File differs from already included file only in casing: correct casing but relative path
ファイルを途中でリネームしたらエラーが起きちゃいました…
VSCodeなのかTypeScriptなのか、元のファイル名情報がどこかに残ってしまっていたようですね。
VSCodeのワークスペースから一回フォルダを消して入れ直せば解消する、という案を見掛けたんですが今回はVSCodeの再起動もしないと解消しませんでした。
TypeScriptの型定義
actionやdispatchの型定義などちょこちょこ書き方わからなくて調べましたね。
今回のようなinitialState, action, reducerのベースを書いてしまえば後は追記していけば良さそうですね。それに、ここで定義しておいた型を各処理で使いまわして型チェックできるので、アプリが大きくなっていく際には重宝しそうです。
まとめ
1~2日ぐらいでuseState使用からuseReducerへ書き換えることができました。
実際には、Reducerの使い方や意図が飲み込めてないとちょっと取っ掛かりにくいかもしれません。
React HookがあればRedux自体は使わなくてもいいんでしょうかね。
useReducerは最初に色々用意が要りますけど、アプリ実装では早めに導入しちゃいたいですね。
では、また〜。
コメント