これは公式のReduxドキュメントの一部です:
これは、渡す関数のタイプであるため、レデューサーと呼ばれます。
Array.prototype.reduce(reducer, ?initialValue)
それは私にはあまり意味がありません。なぜ彼らが実際にレデューサーと呼ばれるのか誰かが私に説明できますか?それらがデフォルト値を返す(またはデフォルトの引数値を持っている)という事実は、それらをレデューサーIMHOにしません。
これは公式のReduxドキュメントの一部です:
これは、渡す関数のタイプであるため、レデューサーと呼ばれます。
Array.prototype.reduce(reducer, ?initialValue)
それは私にはあまり意味がありません。なぜ彼らが実際にレデューサーと呼ばれるのか誰かが私に説明できますか?それらがデフォルト値を返す(またはデフォルトの引数値を持っている)という事実は、それらをレデューサーIMHOにしません。
回答:
それらがデフォルト値を返す(またはデフォルトの引数値を持っている)という事実は、それらをレデューサーIMHOにしません。
レデューサーはデフォルト値を返すだけではありません。それらは常に状態の累積を返します(以前および現在のすべてのアクションに基づいて)。
したがって、それらは状態のリデューサーとして機能します。reduxレデューサーが呼び出されるたびに、アクションとともに状態が渡され(state, action)
ます。次に、この状態はアクションに基づいて削減(または累積)され、次の状態が返されます。これは、クラシックfold
またはreduce
機能の1サイクルです。
@aziumがstate -> action -> state
。と要約されたように。
アプリ内の一連のアクションをリストのようなもの、またはストリームのようなものと見なす場合は、より理にかなっている可能性があります。
この不自然な例を見てください:
['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)
最初の引数は、の形式の関数です(Int, String) => Int
。初期値とともにreduce
、「リデューサー関数」と呼ばれるものを渡すと、一連のアイテムを処理した結果が得られます。つまり、レデューサー関数は、結果を変更するために連続する個々のアイテムで何が行われるかを記述していると言うかもしれません。つまり、レデューサー関数は前の出力と次の値を取得し、次の出力を計算します。
これは、Reduxレデューサーが行うことと類似しています。つまり、前の状態と現在のアクションを取得し、次の状態を計算します。
真の関数型プログラミングスタイルでは、引数と結果に適用される意味を概念的に消去し、入力と出力の「形状」に焦点を合わせることができます。
実際には、Reduxレデューサーは通常、特定のアクションに対してすべてが同じプロパティに変更を加えるわけではないという意味で直交しています。これにより、責任を分割し、出力をで簡単に集約できますcombineReducers
。
すでに述べたように、この名前は関数型プログラミングのレデューサーの概念に関連しています。また、レデューサーのMerriam-Webster辞書の定義が役立つ場合があります。
1a。一緒に描くか、収束させる:統合する(すべての質問を1つに減らす)
レデューサーは、アクションをアプリケーションの状態を表す単一のオブジェクトに統合します。
reduxレデューサーがaと呼ばれる理由は、これらのアクションを実行して結果を取得する
reducer
acollection of actions
とinitial state
(ストアの)を「削減」できるためですfinal state
。
どうやって?これに答えるために、レデューサーをもう一度定義しましょう。
低減()メソッドが適用
function (reducer)
に対してaccumulator
、アレイの各値(左から右へ)は、単一の値に低減します。
そして、reduxレデューサーは何をしますか?
レデューサーは
function
、現在の状態とアクションを取り、次の状態を返す純粋なものです。状態はaccumulated
、コレクションの各アクションがこの状態を変更するために適用されるときのものであることに注意してください。
したがって、が与えられるcollection of actions
と、レデューサーはコレクションの各値に(左から右に)適用されます。初めて、それはを返しますinitial value
。これで、この初期状態と次の状態に戻る最初のアクションにレデューサーが再度適用されます。そして、次のコレクション項目(アクション)が毎回適用され、配列の最後に到達するまでcurrent state
を取得しnext state
ます。そして、あなたは得るthe final state
。なんてクールなんだ!
著者は、状態をreduce関数のアキュムレータと考えています。例:
Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);
reduce関数は関数型プログラミングに由来し、「reducer」という名前もFPに由来します。
ここでその名前を使うのは好きではありません。私は世界を行動後の単一の価値の結果として見ていません。ここの状態はオブジェクトです。例えば:
['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);
このレデューサーは何も削減しません。そして、私はそれが何かを減らすかどうかは気にしません。Transducerという名前を付ける方が理にかなっています。
これからはDeducerと呼んではどうでしょうか。以前の状態と着信アクションに基づいて新しい状態を推測します。
Reduxレデューサーがどのように使用する関数に直接マッピングされているのかよくわかりませんでしreduce
た。そこで、それらがどのように一致するかを確認するための例をいくつか示します。
最初にMDNArray.reduceドキュメントの標準レデューサー(MDNでは「アキュムレータ」と呼ばれます)関数を使用し、次に「Reduxは必要ないかもしれません」というブログ投稿Counter.js
の最後にあるDanAbramovの簡単な例を示します。
sum
アキュムレータに値を追加します reducer
アキュムレータとの間で値を加算/減算します。どちらの場合も、ここでは「状態」は単なる整数です。
アクションを状態に「蓄積」しています。これは、JavaScriptオブジェクトを変更するための不変の方法でもあります。
const sum = function(acc, val) {
return acc + val;
};
const reducer = function(state, action) {
switch (action) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
console.log('sum', [1, -1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0));
console.log('sum', [1, 1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'INCREMENT', 'INCREMENT'].reduce(reducer, 0));
他の回答は、なぜそれがそのままの名前が付けられているのかをよく説明していますが、もっと多くの名前を付けてみましょう...
const origState = 0;
const actionOperators = {
increment: (origState) => origState++,
decrement: (origState) => origState--,
};
const anOperator = (aState, anAction) => actionOperators[anAction](aState);
const actions = ['increment', 'decrement', 'increment'];
const finalState = actions.reduce(anOperator, origState);
まず、reduce
と呼ぶことができますuse anOperator with every action name and accumulated state, starting with origState
。smalltalkではそれはと呼ばれactions inject: origState into: anOperator
ます。しかし、実際にオペレーターに何を注入しますか?origStateとアクション名。そのため、Smalltalkメソッドでも名前はあまり明確ではありません。
actionOperators[increment]
はReducerですが、アクションごとに実装されているため、actionOperatorと呼びます。状態は単なる引数です(そして別の引数は戻り値です)。
ただし、Reducerは、Googleの検索結果の上に表示するのに適した単語です。Reduxにも似ています。
以下のこのコードでは、アキュムレータをアクションとして、currentValueをreduxコンテキストの状態として考える必要があります。この例では、なぜ彼らがそれをレデューサーと名付けているのかがわかります。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// Main operation is 1 + 2 + 3 + 4 = 10
// but think of it as a stack like this:
// | 2 | | 3 | | 4 |
// |_1_| |_3_| |_6_| | 10 | => the 10 is in result
console.log(array1.reduce(reducer));
// expected output: 10
reduce()メソッドは、配列の各要素に対して(指定した)レデューサー関数を実行し、単一の出力値を生成します。
reduce
、デフォルト値と別の値にアクセスできる、渡した関数のように動作し、変換される可能性のあるデフォルト値を返すため、まさにレデューサーです。state -> action -> state