メインコンテンツにスキップ

Reduxの基礎、パート1:Reduxの概要

Reduxの基礎、パート1:Reduxの概要

学習内容
  • Reduxとは何か、なぜそれを使いたいのか
  • Reduxアプリを構成する基本的な要素

はじめに

Reduxの基礎チュートリアルへようこそ!このチュートリアルでは、Reduxを使用するためのコアな概念、原則、およびパターンを紹介します。完了するまでに、Reduxアプリを構成するさまざまな要素、Reduxを使用する際のデータの流れ、およびReduxアプリを構築するための推奨される標準パターンを理解できるようになるはずです。

このチュートリアルのパート1では、Reduxアプリの動作例を簡単に見て、要素を確認します。また、パート2:Reduxの概念とデータフローでは、これらの要素とReduxアプリケーションでのデータの流れについて詳しく見ていきます。

パート3:状態、アクション、リデューサーから、その知識を使用して、これらの要素がどのように適合するかを示す小さなサンプルアプリを構築し、Reduxが実際にどのように機能するかについて説明します。「手作業で」動作するサンプルアプリを構築して、何が起こっているかを正確に確認できるようにした後、Reduxで一般的に使用される標準的なパターンと抽象化について説明します。最後に、これらの低レベルの例が、実際のアプリケーションでの実際の使用に推奨する高レベルのパターンにどのように変換されるかを見ていきます。

このチュートリアルの読み方

このチュートリアルでは、「Reduxがどのように機能するか」だけでなく、これらのパターンがなぜ存在するのかも説明します。

注意

このチュートリアルでは、Reduxの背後にある原則と概念を説明するために、現在Reduxでアプリを構築するための正しいアプローチとして教えるRedux Toolkitを使用した「モダンRedux」パターンよりも多くのコードを必要とする、意図的に古いスタイルのReduxロジックパターンを示していることに注意してください。これは、本番環境に対応したプロジェクトを意図したものではありません

Redux Toolkitを使用した「モダンRedux」の使用方法については、次のページを参照してください。

すべてがどのように適合するかを理解したら、Redux Toolkitを使用して物事を簡略化する方法を見ていきます。Redux Toolkitは、Reduxを使用した本番アプリケーションを構築するための推奨される方法であり、このチュートリアル全体で説明するすべての概念に基づいて構築されています。ここで説明するコアな概念を理解すると、Redux Toolkitをより効率的に使用する方法を理解できます。

これらの説明は初心者向けにわかりやすくするように努めてきましたが、Redux自体の説明に集中できるように、すでに知っていることについていくつかの前提を設ける必要があります。このチュートリアルでは、次の知識があることを前提としています

前提条件

これらのトピックにまだ慣れていない場合は、まずそれらに慣れるために時間をかけてから、Reduxについて学ぶことをお勧めします。準備ができたら、お待ちしています!

最後に、ブラウザにReactとRedux DevTools拡張機能がインストールされていることを確認する必要があります。

Reduxとは?

そもそも、この「Redux」というものが何であるかを理解するのに役立ちます。それは何をするのですか?どのような問題を解決するのに役立ちますか?なぜそれを使いたいのでしょうか?

Reduxは、「アクション」と呼ばれるイベントを使用して、アプリケーションの状態を管理および更新するためのパターンとライブラリです。アプリケーション全体で使用する必要がある状態の集中ストアとして機能し、状態が予測可能な方法でのみ更新されるようにするルールがあります。

なぜReduxを使用する必要があるのですか?

Reduxは、「グローバル」状態、つまりアプリケーションの多くの部分で必要な状態を管理するのに役立ちます。

Reduxが提供するパターンとツールを使用すると、アプリケーションの状態がいつ、どこで、なぜ、どのように更新されているか、およびこれらの変更が発生した場合にアプリケーションロジックがどのように動作するかを理解しやすくなります。Reduxは、予測可能でテスト可能なコードを作成するように導きます。これにより、アプリケーションが期待どおりに動作するという自信が得られます。

いつReduxを使用する必要があるのですか?

Reduxは、共有状態の管理を処理するのに役立ちますが、他のツールと同様に、トレードオフがあります。学ぶべき概念が多く、記述するコードも多くなります。また、コードに間接的な処理が追加され、特定の制限に従う必要があります。これは、短期的な生産性と長期的な生産性のトレードオフです。

Reduxは、次の場合により役立ちます。

  • アプリの多くの場所で必要な大量のアプリケーション状態がある
  • アプリの状態が時間の経過とともに頻繁に更新される
  • その状態を更新するロジックが複雑な場合がある
  • アプリに中規模または大規模なコードベースがあり、多くの人が作業する可能性がある

すべてのアプリにReduxが必要なわけではありません。構築しているアプリの種類について時間をかけて考え、作業している問題の解決に最適なツールを決定してください。

詳細を知りたいですか?

Reduxがアプリに適しているかどうかわからない場合は、これらのリソースでさらにガイダンスを提供します。

Reduxライブラリとツール

Reduxは、小さなスタンドアロンのJSライブラリです。ただし、他のいくつかのパッケージと組み合わせて使用​​されるのが一般的です。

React-Redux

Reduxは任意のUIフレームワークと統合でき、最も頻繁に使用されるのはReactです。React-Reduxは、Reactコンポーネントが状態の一部を読み取り、ストアを更新するアクションをディスパッチすることで、Reduxストアとやり取りできるようにする公式パッケージです。

Redux Toolkit

Redux Toolkitは、Reduxロジックを作成するための推奨されるアプローチです。Reduxアプリの構築に不可欠と思われるパッケージと機能が含まれています。Redux Toolkitは、推奨されるベストプラクティスを組み込み、ほとんどのReduxタスクを簡略化し、一般的な間違いを防ぎ、Reduxアプリケーションを簡単に記述できるようにします。

Redux DevTools拡張機能

Redux DevTools拡張機能は、Reduxストアでの状態の変更履歴を時間の経過とともに表示します。これにより、「タイムトラベルデバッグ」などの強力な手法を使用して、アプリケーションを効果的にデバッグできます。

Reduxの基本

Reduxが何かを理解したので、Reduxアプリを構成する要素とその仕組みについて簡単に見ていきましょう。

情報

このページの説明の残りの部分では、Reduxコアライブラリ(reduxパッケージ)のみに焦点を当てます。チュートリアルの残りの部分を進める中で、Redux関連の他のパッケージについて説明します。

Reduxストア

すべてのReduxアプリケーションの中心は、ストアです。「ストア」とは、アプリケーションのグローバルな状態を保持するコンテナです。

ストアは、普通のグローバルオブジェクトとは異なる、いくつかの特別な機能と能力を備えたJavaScriptオブジェクトです。

  • Reduxストア内に保持されている状態を直接変更したり、変更したりしてはなりません。
  • 代わりに、状態を更新する唯一の方法は、「アプリケーション内で発生した何か」を記述したプレーンなアクションオブジェクトを作成し、何が起こったかをストアに伝えるためにそのアクションをディスパッチすることです。
  • アクションがディスパッチされると、ストアはルートのリデューサー関数を実行し、古い状態とアクションに基づいて新しい状態を計算させます。
  • 最後に、ストアは状態が更新されたことをサブスクライバーに通知し、UIを新しいデータで更新できるようにします。

Reduxコアのサンプルアプリ

Reduxアプリの最小限の動作例である、小さなカウンターアプリケーションを見てみましょう。

Reduxは依存関係のないスタンドアロンのJSライブラリであるため、この例は、Reduxライブラリの単一のスクリプトタグをロードするだけで記述されており、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オブジェクトを持ち、そのオブジェクト内に他の値があります。

次に、リデューサー関数を定義します。リデューサーは、現在のstateと、何が起こったかを記述するactionオブジェクトの2つの引数を受け取ります。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オブジェクトを返す必要があります。元のオブジェクトを直接変更するのではなく、既存の状態をコピーしてコピーを更新することで、状態を不変に更新することに注意してください。

ストア

リデューサー関数ができたので、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を再描画します。

// 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)

この小さな例では、現在の値を表示する単一の<div>を使用して、UIとしていくつかの基本的なHTML要素のみを使用しています。

そこで、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を加算または減算するアクションをディスパッチします。

特定の条件がtrueの場合にのみアクションをディスパッチするコードを記述したり、遅延後にアクションをディスパッチする非同期コードを記述することもできます。

データフロー

Reduxアプリのデータフローは、この図で要約できます。これは、

  • クリックなどのユーザーインタラクションに応じてアクションがディスパッチされる様子を表しています
  • ストアがリデューサー関数を実行して新しい状態を計算する様子
  • UIが新しい状態を読み取って新しい値を表示する様子

(これらの部分がまだはっきりと理解できなくても心配しないでください!このチュートリアルの残りの部分を進めるにつれて、この図を念頭に置いてください。そうすれば、どのように各部分が組み合わさっているかがわかるでしょう。)

Redux data flow diagram

学んだこと

そのカウンターの例は小さかったですが、実際のReduxアプリのすべての動作する部分を示しています。次のセクションで説明するすべての内容は、これらの基本的な部分を拡張したものです。

それを踏まえて、これまでに学んだことを振り返ってみましょう。

概要
  • Reduxは、グローバルなアプリケーションの状態を管理するためのライブラリです。
    • Reduxは通常、ReduxとReactを統合するためのReact-Reduxライブラリとともに使用されます。
    • Redux Toolkitは、Reduxロジックを記述するための推奨される方法です。
  • Reduxは、いくつかのタイプのコードを使用します。
    • アクションは、typeフィールドを持つプレーンなオブジェクトであり、アプリで「何が起こったか」を記述します。
    • リデューサーは、以前の状態+アクションに基づいて新しい状態値を計算する関数です。
    • Reduxストアは、アクションがディスパッチされるたびにルートリデューサーを実行します。

次は何を学ぶか?

Reduxアプリの基本的な要素がわかったところで、パート2:Reduxの概念とデータフローに進みましょう。ここでは、Reduxアプリ内のデータの流れについて詳しく見ていきます。