Reduxの基本 Part 1: Redux概要
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
- Reduxとは何か、なぜ使用するのか
- Reduxアプリを構成する基本要素
はじめに
Redux基礎チュートリアルへようこそ!このチュートリアルではReduxの核となる概念、原則、使用パターンを紹介します。終了時点で、Reduxアプリを構成する各要素、Redux使用時のデータフロー、Reduxアプリ構築の推奨パターンを理解できるようになります。
Part 1では動作する最小限のReduxアプリ例を通じて構成要素を概観し、Part 2: Reduxの概念とデータフローでは各要素の詳細とReduxアプリケーションにおけるデータの流れを深く掘り下げます。
Part 3: 状態、アクション、リデューサからは、これらの知識を活かして実際に動作する小さなアプリを構築し、各要素がどう連携するかを実践的に解説します。動作原理を正確に理解するために最初は手動で構築した後、Reduxで一般的に使用される標準パターンと抽象化について議論します。最後に、これらの低レベルな実装が実際のアプリケーションで推奨される高レベルなパターンにどう発展するかを示します。
このチュートリアルの読み方
このチュートリアルでは「Reduxの動作原理」と、これらのパターンが存在する「理由」を学びます。
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
このチュートリアルでは、Reduxの基本原則と概念を説明するために、あえて旧来のスタイルのReduxロジックパターンを使用しています。これらは、現代的なReduxアプリ開発の正しいアプローチとして推奨しているRedux Toolkitを使った「モダンRedux」パターンに比べてコード量が多くなります。このチュートリアルは_プロダクション環境で使用することを想定したものではありません_。
「モダンRedux」をRedux Toolkitで実践する方法については、以下のページを参照してください:
- 完全版「Redux Essentials」チュートリアル: 現実世界のアプリケーションでRedux Toolkitを使った「Reduxの正しい使い方」を解説しています。すべてのRedux学習者は「Essentials」チュートリアルの読了を推奨します!
- Redux Fundamentals パート8: Redux ToolkitによるモダンRedux: 前半セクションのローレベルな例をモダンなRedux Toolkitの実装に変換する方法を解説
全体の仕組みを理解した後は、Redux Toolkitを使用して作業を簡素化する方法を見ていきます。Redux ToolkitはReduxを使った本番アプリ構築の推奨手法であり、このチュートリアルで扱う全ての概念に基づいています。ここで学ぶ核心理念を理解すれば、Redux Toolkitをより効率的に活用できるようになります。
説明は初心者向けを心がけていますが、Redux自体の解説に集中するため、以下の前提知識があることを想定しています:
- HTML & CSSの基礎知識
- ES2015構文と機能の理解
- 配列/オブジェクトのスプレッド演算子の理解
- React用語の知識: JSX, 関数コンポーネント, Props, State, Hooks
- 非同期JavaScriptとHTTPリクエストの知識
これらのトピックに不安がある場合は、まずそれらを理解する時間を取ってから、Reduxの学習に戻ってくることをお勧めします。準備が整うまで、いつでもお待ちしています!
最後に、ブラウザにReactとReduxのDevTools拡張機能がインストールされていることを確認してください:
-
React DevTools拡張機能:
-
Redux DevTools拡張機能:
Reduxとは?
まず「Redux」とは何かを理解しましょう。何をするツールなのか?どんな問題解決に役立つのか?なぜ使いたいと思うのか?
Reduxはグローバルなアプリケーション状態を管理・更新するためのパターンおよびライブラリです。UIが「アクション」と呼ばれるイベントをトリガーして発生した事象を記述し、「リデューサ」と呼ばれる更新ロジックがそれに応じて状態を更新します。アプリケーション全体で共有される状態を一元管理するストアとして機能し、状態が予測可能な方法でのみ更新されることを保証するルールを備えています。
Reduxを使うべき理由
Reduxは「グローバル」な状態、つまりアプリケーションの多くの部分で必要とされる状態の管理を支援します。
Reduxが提供するパターンとツールは、アプリケーションの状態がいつ、どこで、なぜ、どのように更新されるのか、またその変化が発生した際にアプリケーションロジックがどう振る舞うのかを理解しやすくします。Reduxは予測可能でテスト可能なコード作成を導くため、アプリケーションが期待通りに動作するという確信を得るのに役立ちます。
Reduxを使うべきタイミング
Reduxは共有状態管理を支援しますが、あらゆるツールと同様にトレードオフがあります。学習すべき概念が増え、記述するコードも増加します。またコードに間接性が加わり、一定の制約に従う必要があります。これは短期生産性と長期生産性のトレードオフです。
Reduxが特に有用なケース:
-
アプリケーションの状態が大量にあり、アプリ内の多くの場所で必要となる場合
-
アプリケーションの状態が時間とともに頻繁に更新される場合
-
状態を更新するロジックが複雑になる可能性がある場合
-
中規模〜大規模のコードベースを持ち、多くの開発者が関わる可能性がある場合
すべてのアプリがReduxを必要とするわけではありません。自身が開発しているアプリの種類をよく考え、解決すべき問題に最適なツールを選択してください。
Reduxがアプリに適しているか判断できない場合、以下のリソースが参考になります:
Redux関連ライブラリとツール
Reduxは独立した小さなJSライブラリですが、通常は以下のパッケージと併用されます:
Redux Toolkit
Redux ToolkitはReduxロジック記述における推奨アプローチです。Reduxアプリ構築に不可欠なパッケージと関数を提供し、ベストプラクティスの組み込み、タスクの簡略化、一般的なミスの防止、アプリ開発の効率化を実現します。
React-Redux
ReduxはあらゆるUIフレームワークと統合可能ですが、最も頻繁にReactと併用されます。React-Reduxは公式パッケージで、Reactコンポーネントが状態の読み取りやストア更新のアクション発行を通じてReduxストアと連携します。
Redux DevTools拡張機能
Redux DevTools拡張機能はReduxストアの状態変更履歴を可視化します。"タイムトラベルデバッグ"などの強力な手法を含め、効果的なアプリデバッグを可能にします。
Reduxの基本
Reduxとは何かを理解したところで、Reduxアプリを構成する要素とその動作を簡単に見ていきましょう。
このページの残りの説明はReduxコアライブラリ(reduxパッケージ)のみに焦点を当てています。他の関連パッケージはチュートリアル後半で解説します。
Reduxストア
すべてのReduxアプリケーションの中心となるのがストアです。「ストア」はアプリケーションのグローバルな状態を保持するコンテナです。
ストアはJavaScriptオブジェクトですが、通常のグローバルオブジェクトと異なる特殊な関数と機能を備えています:
-
Reduxストア内のステートを直接変更してはいけません
-
代わりに、ステートを更新する唯一の方法は、アプリケーションで「何かが起きた」ことを記述するプレーンなアクションオブジェクトを作成し、そのアクションをストアにディスパッチして何が起きたかを伝えることです
-
アクションがディスパッチされると、ストアはルートリデューサ関数を実行し、古いステートとアクションに基づいて新しいステートを計算させます
-
最後に、ストアはステートが更新されたことをサブスクライバーに通知し、UIが新しいデータで更新されるようにします
Reduxコアのサンプルアプリ
Reduxアプリの最小限の動作例、小さなカウンターアプリケーションを見てみましょう:
Reduxは依存関係のないスタンドアロンのJSライブラリであるため、この例ではReduxライブラリ用の単一のscriptタグを読み込むだけで作成されており、UIには基本的なJSとHTMLを使用しています。実際には、Reduxは通常NPMからReduxパッケージをインストールして使用され、UIはReactのようなライブラリで作成されます。
第5章: UIとReactでは、ReduxとReactを一緒に使う方法を説明しています。
この例を個々のパーツに分解して、何が起きているのかを見てみましょう。
ステート、アクション、リデューサ
まずアプリケーションを記述するための初期ステート値を定義します:
// Define an initial state value for the app
const initialState = {
value: 0
}
このアプリでは、カウンターの現在値を示す単一の数値を追跡します。
Reduxアプリでは通常、ステートのルート部分としてJSオブジェクトを持ち、そのオブジェクト内に他の値を保持します。
次にリデューサ関数を定義します。リデューサは2つの引数、現在のstateと発生した事象を記述するactionオブジェクトを受け取ります。Reduxアプリ起動時にはまだステートがないため、このリデューサのデフォルト値としてinitialStateを提供します:
// Create a "reducer" function that determines what the new state
// should be when something happens in the app
function counterReducer(state = initialState, action) {
// Reducers usually look at the type of action that happened
// to decide how to update the state
switch (action.type) {
case 'counter/incremented':
return { ...state, value: state.value + 1 }
case 'counter/decremented':
return { ...state, value: state.value - 1 }
default:
// If the reducer doesn't care about this action type,
// return the existing state unchanged
return state
}
}
アクションオブジェクトには常にtypeフィールドがあり、これはアクションの一意な名前として機能する文字列です。typeは可読性の高い名前にすべきで、このコードを見た誰もがその意味を理解できるようにします。この例では、アクションタイプの前半に'counter'、後半に「何が起きたか」の説明を付けます。ここではカウンターがインクリメントされたので、アクションタイプを'counter/incremented'と記述します。
アクションのタイプに基づいて、新しいstate結果となる全く新しいオブジェクトを返すか、変更が必要ない場合は既存のstateオブジェクトを返します。ステートを更新する際は、元のオブジェクトを直接変更するのではなく、既存のステートをコピーしてそのコピーを更新することで、_不変(イミュータブル)に_更新することに注意してください。
ストア(Store)
リデューサ関数ができたので、ReduxライブラリのcreateStore APIを呼び出してストアインスタンスを作成できます。
// Create a new Redux store with the `createStore` function,
// and use the `counterReducer` for the update logic
const store = Redux.createStore(counterReducer)
リデューサ関数をcreateStoreに渡すと、この関数を使って初期ステートを生成し、将来の更新を計算します。
UI
どのアプリケーションでも、ユーザーインターフェース(UI)は既存のステートを画面に表示します。ユーザーが何かを行うと、アプリはデータを更新し、その値でUIを再描画します。
// Our "user interface" is some text in a single HTML element
const valueEl = document.getElementById('value')
// Whenever the store state changes, update the UI by
// reading the latest store state and showing new data
function render() {
const state = store.getState()
valueEl.innerHTML = state.value.toString()
}
// Update the UI with the initial data
render()
// And subscribe to redraw whenever the data changes in the future
store.subscribe(render)
この小さな例では、基本的なHTML要素のみをUIとして使用し、現在の値を表示する単一の<div>要素を使っています。
そこで、store.getState()メソッドを使ってReduxストアから最新のステートを取得し、その値を用いてUIを更新して表示する関数を作成します。
Reduxストアのstore.subscribe()メソッドを呼び出すことで、ストアが更新されるたびに実行されるサブスクライバーコールバック関数を登録できます。ここではrender関数をサブスクライバーとして渡しているため、ストアが更新される度に最新の値でUIを更新できます。
Redux自体はスタンドアロンのライブラリであり、あらゆる環境で使用可能です。つまり、任意のUIレイヤーと組み合わせて利用できます。
アクションのディスパッチ
最後に、ユーザー入力に応答するために、発生した事象を記述したアクションオブジェクトを作成し、ストアへディスパッチする必要があります。store.dispatch(action)を呼び出すと、ストアはリデューサを実行し、更新された状態を計算し、サブスクライバーを実行してUIを更新します。
// Handle user inputs by "dispatching" action objects,
// which should describe "what happened" in the app
document.getElementById('increment').addEventListener('click', function () {
store.dispatch({ type: 'counter/incremented' })
})
document.getElementById('decrement').addEventListener('click', function () {
store.dispatch({ type: 'counter/decremented' })
})
document
.getElementById('incrementIfOdd')
.addEventListener('click', function () {
// We can write logic to decide what to do based on the state
if (store.getState().value % 2 !== 0) {
store.dispatch({ type: 'counter/incremented' })
}
})
document
.getElementById('incrementAsync')
.addEventListener('click', function () {
// We can also write async logic that interacts with the store
setTimeout(function () {
store.dispatch({ type: 'counter/incremented' })
}, 1000)
})
ここでは、リデューサに現在のカウンター値を1増加または減少させるアクションをディスパッチします。
特定の条件が真の場合にのみアクションをディスパッチするコードや、遅延後にアクションをディスパッチする非同期コードも記述可能です。
データフロー
Reduxアプリケーションにおけるデータフローは以下の図で要約できます。これは以下の流れを表現しています:
-
クリックなどのユーザー操作に応答してアクションがディスパッチされる
-
ストアがリデューサ関数を実行して新しい状態を計算する
-
UIが新しい状態を読み取り、更新された値を表示する
(これらの要素がまだ完全に明確でなくても心配ありません!このチュートリアルの残りを進めながらこの図を頭に留めておくと、各要素がどう連携するかが見えてきます。)

学んだこと
このカウンターの例は小規模ですが、実際のReduxアプリケーションのすべての機能要素を示しています。 以降のセクションで説明する内容は、すべてこれらの基本要素を拡張したものです。
このことを念頭に置き、これまでに学んだ内容を振り返りましょう:
- Reduxはグローバルなアプリケーション状態を管理するライブラリ
- Reduxは通常、Reactと統合するためのReact-Reduxライブラリと併用
- Redux ToolkitはReduxロジックを記述する標準的な方法
- Reduxの更新パターンでは「何が起きたか」と「状態がどう変化するか」が分離
- アクション は
typeフィールドを持つプレーンオブジェクトで、アプリ内で「何が起きたか」を記述 - リデューサー は前の状態とアクションに基づいて新しい状態値を計算する関数
- Redux ストア はアクションが_ディスパッチ_されるたびにルートリデューサーを実行
- アクション は
- Reduxは「単方向データフロー」アプリ構造を採用
- 状態は特定時点のアプリ状態を記述し、UIはその状態に基づいてレンダリング
- アプリで何かが発生すると:
- UIがアクションをディスパッチ
- ストアがリデューサーを実行し、発生した内容に基づいて状態を更新
- ストアが状態変更をUIに通知
- UIは新しい状態に基づいて再レンダリング
次のステップ
Reduxアプリの基本構成要素を理解したところで、次のパート2:Reduxの概念とデータフローに進み、Reduxアプリケーションにおけるデータフローをより詳細に確認しましょう。