なぜRedux Toolkitが今日のReduxの使い方なのか
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
Redux Toolkitとは
Redux Toolkit(略称 RTK)は、Reduxロジックを記述するための公式推奨アプローチです。@reduxjs/toolkitパッケージはコアのreduxパッケージをラップし、Reduxアプリ構築に必須と考えられるAPIメソッドと共通依存関係を含んでいます。Redux Toolkitは推奨ベストプラクティスを組み込み、ほとんどのReduxタスクを簡素化し、一般的なミスを防止し、Reduxアプリケーションの開発を容易にします。
現在Reduxロジックを記述する場合、すべてのコードでRedux Toolkitを使用すべきです!
RTKにはストア設定、不変更新ロジックを用いたReducer作成、状態の「スライス」一括生成など、一般的なユースケースを簡素化するユーティリティが含まれます。
初めてプロジェクトをセットアップする新規ユーザーでも、既存アプリケーションを簡素化したい経験豊富なユーザーでも、**Redux Toolkit**はReduxコードの改善に役立ちます。
Redux Toolkitを使った「モダンなRedux」の学習リソース:
- 実践アプリ向けにRedux Toolkitを使った「正しいReduxの使い方」を教える「Redux Essentials」チュートリアル
- チュートリアル前半の低レベルな例をモダンなRedux Toolkitに変換する方法を示すRedux Fundamentals Part 8: Redux Toolkitを使ったモダンなRedux
- 各種レガシーReduxロジックをモダンな実装に移行する方法をカバーするUsing Redux: モダンなReduxへの移行
Redux ToolkitとコアReduxの違い
「Redux」とは何か
まず「Reduxとは何か」を考えましょう。
Reduxの本質は:
-
「グローバル」状態を含む単一ストア
-
アプリで発生した事象をプレーンオブジェクトのアクションとしてストアへディスパッチ
-
不変更新された状態を返すピュアなReducer関数
必須ではありませんが、通常Reduxコードには以下も含まれます:
-
アクションオブジェクトを生成するアクションクリエイター
-
副作用を可能にするミドルウェア
-
同期/非同期ロジックと副作用を含むThunk関数
-
IDによるアイテム検索を可能にする正規化状態
-
派生データ最適化のためのReselectライブラリを使ったメモ化セレクター関数
-
アクション履歴と状態変化を表示するRedux DevTools拡張
-
アクション・状態・その他関数のTypeScript型
さらに、Reduxは通常React-Reduxライブラリと併用され、ReactコンポーネントがReduxストアと通信します。
Reduxコアの役割
Reduxコアは意図的に非主張的で非常に小さなライブラリです。提供するAPIプリミティブ:
-
Reduxストアを実生成する
createStore -
複数スライスReducerを単一Reducerに結合する
combineReducers -
複数ミドルウェアをストアエンハンサーに結合する
applyMiddleware -
複数ストアエンハンサーを単一エンハンサーに結合する
compose
これ以外のRedux関連ロジックはすべて自身で実装する必要があります。
良い点はReduxが多様な方法で使用可能なこと、悪い点はコード記述を容易にするヘルパーが存在しないことです。
例: Reducer関数は単なる関数です。Redux Toolkit以前は通常、switch文と手動更新でReducerを記述しました。手書きのアクションクリエイターとアクションタイプ定数も併せて作成するのが一般的でした:
const ADD_TODO = 'ADD_TODO'
const TODO_TOGGLED = 'TODO_TOGGLED'
export const addTodo = text => ({
type: ADD_TODO,
payload: { text, id: nanoid() }
})
export const todoToggled = id => ({
type: TODO_TOGGLED,
payload: id
})
export const todosReducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return state.concat({
id: action.payload.id,
text: action.payload.text,
completed: false
})
case TODO_TOGGLED:
return state.map(todo => {
if (todo.id !== action.payload) return todo
return {
...todo,
completed: !todo.completed
}
})
default:
return state
}
}
このコードはreduxコアライブラリのAPIに依存しません。しかし記述量が多く、不変更新には多くの手動オブジェクトスプレッドや配列操作が必要で、状態の誤った変更(Reduxバグの常に第1位!)が起きやすくなります。また厳密には必須ではありませんが、actions/todos.js、constants/todos.js、reducers/todos.jsのように単一機能のコードを複数ファイルに分割するのも一般的でした。
さらに、ストア設定には通常、Thunkのような一般的なミドルウェアの追加やRedux DevTools拡張の有効化など、ほぼすべてのReduxアプリで使用される標準ツールのセットアップ手順が必要でした。
Redux Toolkitの役割
これらは元々Reduxドキュメントで紹介されたパターンですが、残念ながら非常に冗長で繰り返しの多いコードを必要とします。この定型コードの大半はRedux使用に必須ではありません。加えて、定型コードはミスの機会を増やします。
Redux Toolkitは、手書きReduxロジックから「定型コード」を排除し、一般的なミスを防止し、標準Reduxタスクを簡素化するAPIを提供するために特別に作成されました。
Redux Toolkitは、すべてのReduxアプリで共通する重要なタスクを簡素化する2つのAPIから始まります:
-
configureStore: 単一関数呼び出しで適切に設定されたReduxストアをセットアップ(Reducer結合、Thunkミドルウェア追加、DevTools統合を含む)。createStoreより設定が容易(名前付きオプションパラメータ採用) -
createSlice: Immerライブラリを使用し、state.value = 123のような「変更」JS構文で不変更新を記述可能に(スプレッド不要)。各Reducerのアクションクリエイター関数と、Reducer名に基づくアクションタイプ文字列を自動生成。TypeScriptと高い親和性
これにより実装コードを劇的に簡素化できます。例えば前述のTodoReducerは以下で済みます:
import { createSlice } from '@reduxjs/toolkit'
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
todoAdded(state, action) {
state.push({
id: action.payload.id,
text: action.payload.text,
completed: false
})
},
todoToggled(state, action) {
const todo = state.find(todo => todo.id === action.payload)
todo.completed = !todo.completed
}
}
})
export const { todoAdded, todoToggled } = todosSlice.actions
export default todosSlice.reducer
すべてのアクションクリエイターとアクションタイプが自動生成され、Reducerコードは短く理解しやすくなります。各ケースでの実際の更新内容も明確です。
configureStoreを使用すると、ストア設定は以下に簡略化されます:
import { configureStore } from '@reduxjs/toolkit'
import todosReducer from '../features/todos/todosSlice'
import filtersReducer from '../features/filters/filtersSlice'
export const store = configureStore({
reducer: {
todos: todosReducer,
filters: filtersReducer
}
})
この単一のconfigureStore呼び出しが、手動で行う標準セットアップ作業をすべて自動化します:
-
スライスReducerの
combineReducers()への自動引き渡し -
redux-thunkミドルウェアの自動追加 -
誤変更を検知する開発用ミドルウェアの追加
-
Redux DevTools拡張の自動セットアップ
-
ミドルウェアとDevToolsエンハンサーの自動合成とストアへの追加
同時に**configureStoreは、デフォルト動作を変更するオプションを提供します**(Thunk無効化+Saga追加、本番環境でのDevTools無効化など)。
さらにRedux Toolkitには、一般的なReduxタスク向けの他のAPIが含まれます:
-
createAsyncThunk: 「非同期リクエスト前後のアクションディスパッチ」パターンを抽象化 -
createEntityAdapter: 正規化された状態に対するCRUD操作のための事前構築済みリデューサーとセレクター -
createSelector: メモ化されたセレクターのための標準Reselect APIの再エクスポート -
createListenerMiddleware: ディスパッチされたアクションに応答してロジックを実行するための副作用ミドルウェア
最後に、RTKパッケージには「RTK Query」も含まれています。これはReduxアプリのための完全なデータ取得&キャッシュソリューションで、別途オプションの@reduxjs/toolkit/queryエントリポイントとして提供されます。エンドポイント(REST、GraphQL、任意の非同期関数)を定義でき、データ取得、ローディング状態の更新、結果のキャッシュを完全に管理するリデューサーとミドルウェアを生成します。また、コンポーネント内でデータ取得に使用できるReactフックを自動生成します(例:const { data, isFetching } = useGetPokemonQuery('pikachu'))
これらのAPIはすべて完全にオプションであり特定のユースケース向けに設計されています。アプリで実際に使用するAPIを選択可能ですが、これらのタスクを支援するためすべて強く推奨されます。
重要なのはRedux Toolkitも依然として「Redux」であることです!単一ストア、更新のためのディスパッチされるアクションオブジェクト、不変的に状態を更新するリデューサー、非同期ロジックのためのサンク、正規化状態管理、TypeScriptによる型付け、DevToolsの使用——すべてが存在します。同じ結果を得るために書くコード量が大幅に減っただけです!
なぜRedux Toolkitの使用を推奨するのか
Reduxメンテナーとしての私たちの見解:
すべてのReduxユーザーにRedux Toolkitでコードを書くことを推奨します。コードが簡素化され、多くの一般的なReduxのミスやバグを排除できるからです!
初期のReduxパターンに見られた「ボイラープレート」と複雑さは、Reduxの本質的な部分ではありませんでした。これらのパターンが存在した理由は:
-
元々の「Fluxアーキテクチャ」が同様のアプローチを採用していた
-
初期のReduxドキュメントが、タイプ別にコードを分割するためのアクションタイプ定数などを示していた
-
JavaScriptがデフォルトで可変言語であり、不変更新には手動のオブジェクトスプレッドや配列操作が必要だった
-
Reduxが当初わずか数週間で構築され、意図的に少数のAPIプリミティブのみに設計されていた
さらにReduxコミュニティでは、追加のボイラープレートを生む特定のアプローチが採用されました:
-
副作用処理の一般的な方法として
redux-sagaミドルウェアの使用が強調された -
Reduxアクションオブジェクトの手書きTS型と、型レベルでディスパッチ可能なアクションを制限するユニオン型の作成が求められた
長年にわたり、実際にReduxがどのように使用されているかを観察してきました。コミュニティが、アクションタイプ/クリエイター生成、非同期ロジック/副作用、データ取得など向けに数百のアドオンライブラリを作成する様子も見てきました。同時に、状態の誤った変更(Reduxバグの第1位)、単純な状態更新に何十行ものコードが必要なこと、コードベースの関連性を追跡する困難さなど、ユーザーを悩ませ続ける問題も目の当たりにしました。Reduxの学習や使用に苦労し、概念の多さや余分なコード量に困惑する数千人のユーザーを支援してきました。ユーザーが直面する問題を私たちは熟知しています。
Redux Toolkitはこれらの問題を解決するために特別に設計されました!
-
ストア設定を単一の明確な関数呼び出しに簡素化(必要な場合のストアオプション完全設定機能は保持)
-
Reduxバグの第1原因である誤った変更を排除
-
アクションクリエイターやアクションタイプの手書きを不要化
-
エラーが発生しやすい手動の不変更新ロジックを不要化
-
複数のファイルに分散せず、1ファイルでRedux機能のコードを記述可能に
Redux Toolkitは優れたTypeScriptサポートを提供し、APIは優れた型安全性を実現し、コード内で定義する必要のある型の数を最小限に抑えるように設計されています
RTK Queryを使用すると、データ取得やローディング状態の管理のために_thunk_、reducer、action creator、エフェクトフックを記述する必要が完全になくなります
このため:
今日Reduxを使用するすべてのユーザーは、必ずRedux Toolkit(@reduxjs/toolkitパッケージ)を使用すべきであり、新しいReduxコードには従来のreduxコアパッケージを決して使用すべきではありません!
既存のアプリケーションでも、少なくともcreateStoreをconfigureStoreに切り替えることをお勧めします。開発モードのミドルウェアは、既存のコードベースでの意図しない変更やシリアライズ可能性エラーの検出にも役立ちます。また、頻繁に使用するreducer(および今後作成するもの)をcreateSliceに切り替えることを強く推奨します。コードは短く理解しやすくなり、安全性の向上により将来の時間と労力を節約できます。
reduxコアパッケージは引き続き機能しますが、今日では廃止予定とみなしています。すべてのAPIは@reduxjs/toolkitから再エクスポートされており、configureStoreはcreateStoreのすべての機能を、より優れたデフォルト動作と設定可能性を備えて実現します。
低レベルの概念を理解することは有用です。Redux Toolkitが何をしているのかをより深く理解するためです。これが「Redux Fundamentals」チュートリアルで抽象化せずにReduxの動作を説明している理由です。ただし、これらの例は学習ツールとしてのみ示しており、最後にRedux Toolkitが従来の手書きReduxコードをどのように簡素化するかを示しています。
reduxコアパッケージを単独で使用している場合、コードは引き続き動作します。しかし、@reduxjs/toolkitへの移行と、Redux Toolkit APIを使用するようにコードを更新することを強くお勧めします!
参考情報
詳細については以下のドキュメントページとブログ記事を参照してください: