このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
コアコンセプト
アプリケーションの状態(state)がプレーンオブジェクトで表現されると想像してください。例えば、TODOアプリの状態は次のようになります:
{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
このオブジェクトは「モデル」のようなものですが、セッターが存在しません。これにより、コードの異なる部分が状態を任意に変更して再現困難なバグを引き起こすのを防ぎます。
状態を変更するには、アクションをディスパッチする必要があります。アクションとは(ここでは何も特別な仕掛けを導入しないことに注目)、発生した事象を記述するプレーンなJavaScriptオブジェクトです。以下にアクションの例を示します:
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
すべての変更をアクションとして記述するルールを設けることで、アプリ内で何が起きているかを明確に理解できます。何かが変更された場合、その理由がわかります。アクションは発生した事象の軌跡のようなものです。 最後に、状態とアクションを結びつけるためにリデューサーと呼ばれる関数を作成します。これも特別なものではなく、状態とアクションを引数に取り、アプリの次の状態を返す単なる関数です。 大規模なアプリではこのような関数を作成するのが難しいため、状態の一部を管理する小さな関数を複数作成します:
function visibilityFilter(state = 'SHOW_ALL', action) {
if (action.type === 'SET_VISIBILITY_FILTER') {
return action.filter
} else {
return state
}
}
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }])
case 'TOGGLE_TODO':
return state.map((todo, index) =>
action.index === index
? { text: todo.text, completed: !todo.completed }
: todo
)
default:
return state
}
}
そして、対応する状態キーに対してこれら2つのリデューサーを呼び出す別のリデューサーを作成し、アプリ全体の状態を管理します:
function todoApp(state = {}, action) {
return {
todos: todos(state.todos, action),
visibilityFilter: visibilityFilter(state.visibilityFilter, action)
}
}
これがReduxの基本的な考え方の全体像です。ここではRedux APIを一切使用していないことに注目してください。Reduxにはこのパターンを容易にするユーティリティが含まれていますが、核となるアイデアは「アクションオブジェクトに応じて状態がどのように更新されるかを時間軸で記述する」ことです。また、作成するコードの90%はプレーンなJavaScriptであり、Redux自体やそのAPI、あるいは特別な仕掛けは一切使用しません。