Warum werden Redux-Zustandsfunktionen als Reduzierer bezeichnet?


82

Dies ist ein Teil der offiziellen Redux-Dokumentation :

Es wird als Reduzierer bezeichnet, da dies die Art von Funktion ist, an die Sie übergeben würden Array.prototype.reduce(reducer, ?initialValue)

Es macht für mich nicht viel Sinn. Könnte mir jemand erklären, warum sie eigentlich Reduzierer genannt werden? Die Tatsache, dass sie einen Standardwert zurückgeben (oder einen Standardargumentwert haben), macht sie meiner Meinung nach nicht zu Reduzierern.


6
Sie sind Reduzierer, genau weil sie sich wie die Funktion verhalten, an die Sie übergeben reduce, die Zugriff auf den Standardwert und einen anderen Wert hat und Ihnen Ihren potenziell transformierten Standardwert zurückgibt. state -> action -> state
Azium

2
eine Rose mit einem anderen Namen ... wahrscheinlich Marketing; Karte / reduzieren ist jetzt ein Schlagwort ...
Dandavis

1
Deshalb müssen Sie anfangen, sich selbst zu denken und sich nicht auf einen Rahmen verlassen. Ein Framwork ist meistens die Arbeit eines oder mehrerer Entwickler mit ihrer eigenen Vision, wie ein von Internetnutzern angepasstes Problem gelöst werden kann. Einige Frameworks haben es richtig gemacht, meistens jedoch nicht. Ein Blizz eines Kusses, gleich oder weniger, ist keine Lösung. Dies ist nur ein Beispiel für viele da draußen.
Codebeat

Antworten:


70

Die Tatsache, dass sie einen Standardwert zurückgeben (oder einen Standardargumentwert haben), macht sie meiner Meinung nach nicht zu Reduzierern.

Reduzierstücke nicht nur Standardwerte zurück. Sie geben immer die Akkumulation des Zustands zurück (basierend auf allen vorherigen und aktuellen Aktionen).

Daher wirken sie als Minderer des Staates. Jedes Mal, wenn ein Redux-Reduzierer aufgerufen wird, wird der Status mit der Aktion übergeben (state, action). Dieser Zustand wird dann basierend auf der Aktion reduziert (oder akkumuliert), und dann wird der nächste Zustand zurückgegeben. Dies ist ein Zyklus des Klassikers foldoder der reduceFunktion.

Wie @azium mit zusammenfasste state -> action -> state.


7
Humm nach dieser Logik sollten sie nicht eher Erhöher als Reduzierer genannt werden? Es werden nie Daten reduziert, die hinzugefügt werden: / lol
Jamie Hutber

16
@JamieHutber Ich denke, Sie vermissen die Bedeutung von Reduzierer in diesem Zusammenhang etwas. Der Reduzierer nimmt einen Stream (oder eine Sammlung) von Elementen und kombiniert sie zu einem einzelnen Element. In diesem Fall sind alle Aktionen (im Laufe der Zeit) die Sammlung von Elementen, und der Status ist das einzelne Element. Sinn ergeben?
Davin Tryon

7
lol ich sehe jetzt. Es geht also im Grunde nur darum, sie zu konzentrieren. Warum nennst du es dann nicht Fusion? P Danke, dass du es mir klar gemacht hast :)
Jamie Hutber

20
Gott sei Dank bin ich nicht der einzige, der denkt, dass der Namensreduzierer zum Zeitpunkt des Schreibens ein wenig von mindestens 2.000 Ansichten in diesem Beitrag abweicht. Die Tatsache, dass jemand sogar bereit ist, die Anstrengungen zu unternehmen, um herauszufinden, warum es als Reduzierer bezeichnet wird, bedeutet nicht, dass es tatsächlich ein bisschen anders ist? Wenn es als Reduzierer bezeichnet wird, weil es die Art von Funktion ist, die Sie an Array.prototype.reduce übergeben würden, ist es so, als würden wir Orange als Entsafter bezeichnen, weil wir Orange an object.prototype.juicer übergeben, oder sollten wir es nicht als Frucht bezeichnen?
Yini

2
Ich stimme zu, es ist überhaupt kein intuitiver Name. Logischerweise sollte es etwas reduzieren, um als Reduzierer bezeichnet zu werden. Wenn eine ganze Reihe von Zustandsänderungen zusammen mit einem Zustand auf einmal zu einem einzigen Zustand zusammengefasst würde, wäre dies ein intuitiver Name.
Peter Evan Deal

20

Wenn Sie die Reihe von Aktionen in Ihrer App als eine Liste oder eher als einen Stream betrachten, ist dies möglicherweise sinnvoller.

Nehmen Sie dieses erfundene Beispiel:

['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)

Das erste Argument ist eine Funktion des Formulars (Int, String) => Int. Zusammen mit einem Anfangswert übergeben Siereduce eine sogenannte "Reduzierungsfunktion" und erhalten das Ergebnis der Verarbeitung der Artikelserie. Man könnte also sagen, dass die Reduzierungsfunktion beschreibt, was mit jedem einzelnen Element getan wird, um das Ergebnis zu ändern. Mit anderen Worten, die Reduzierungsfunktion nimmt die vorherige Ausgabe und den nächsten Wert und berechnet die nächste Ausgabe.

Dies ist analog zu dem, was ein Redux-Reduzierer tut: Er nimmt den vorherigen Zustand und die aktuelle Aktion an und berechnet den nächsten Zustand.

Im echten funktionalen Programmierstil können Sie die Bedeutung der Argumente und des Ergebnisses konzeptionell löschen und sich nur auf die "Form" der Ein- und Ausgaben konzentrieren.

In der Praxis sind Redux-Reduzierer in der Regel orthogonal, da sie für eine bestimmte Aktion nicht alle Änderungen an denselben Eigenschaften vornehmen, wodurch es einfach ist, ihre Verantwortlichkeiten aufzuteilen und die Ausgabe mit zu aggregieren combineReducers.


Ja, Sie haben Recht, es ist sinnvoller, wenn ich über Aktionen nachdenke, die eher einem Stream ähneln. Cool, interpretiere das!
Anton Savchenko

So habe ich es ursprünglich verstanden, aber es scheint nicht so zu sein, wie es eine der Store-Implementierungen, die ich bisher gesehen habe, implementiert hat ...
Boris Callens

16

Wie bereits erwähnt, bezieht sich der Name auf das Konzept eines Reduzierers in der funktionalen Programmierung. Möglicherweise ist auch die Definition des Reduzierers im Merriam-Webster-Wörterbuch hilfreich:

1a. zusammenziehen oder konvergieren lassen: konsolidieren (alle Fragen auf eins reduzieren)

Der Reduzierer konsolidiert Aktionen in einem einzelnen Objekt, das den Anwendungsstatus darstellt.


8

Der Grund, warum ein Redux-Reduzierer als a bezeichnet wird, reducerliegt darin, dass Sie a collection of actionsund a initial state(des Geschäfts) "reduzieren" können , um diese Aktionen auszuführen, um das Ergebnis zu erhalten final state.

Wie? Um dies zu beantworten, möchte ich noch einmal einen Reduzierer definieren:

Die Methode redu () wendet ein function (reducer)gegen einen accumulatorund jeden Wert des Arrays (von links nach rechts) an, um es auf einen einzelnen Wert zu reduzieren.

Und was macht ein Redux-Reduzierer?

Der Reduzierer ist ein reiner functionStatus, der den aktuellen Status und eine Aktion übernimmt und den nächsten Status zurückgibt. Beachten Sie, dass der Status so ist, accumulatedwie jede Aktion in der Sammlung angewendet wird, um diesen Status zu ändern.

Bei a collection of actionswird der Reduzierer auf jeden Wert der Sammlung angewendet (von links nach rechts). Beim ersten Mal wird das zurückgegeben initial value. Jetzt wird der Reduzierer erneut auf diesen Anfangszustand und die erste Aktion angewendet, um den nächsten Zustand zurückzugeben. Und das nächste Sammlungselement (Aktion) wird jedes Mal auf das angewendet current state, um das zu erhalten, next statebis es das Ende des Arrays erreicht. Und dann bekommst du the final state. Wie cool ist das!


5

Der Autor denkt Zustand als Akkumulator der Reduktionsfunktion. Ex:

Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);

Die Reduktionsfunktion stammt von Functional Programming, der Name "Reducer" stammt ebenfalls von FP.

Ich mag es nicht, diesen Namen hier zu verwenden. Weil ich die Welt nach Aktionen nicht als ein einziges Wertergebnis sehe. Der Zustand hier ist ein Objekt. Beispielsweise:

['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);

Diese Reducer reduziert nichts. Und es ist mir egal, ob es irgendetwas reduziert oder nicht. Es wird sinnvoller sein, es als Transducer zu bezeichnen.


5

Wir wissen, woher Reduzierer kommen (funktionale Programmierung) und warum sie möglicherweise weniger Arbeit leisten (reduzieren Sie n Eingabeelemente auf einen einzigen Rückgabewert - genau das tun normale Funktionen). Allerdings: Der Name ist nur ein Name, wie Rose der Name für eine Rose ist. Nicht zu viel nachdenken. Redux-Programmierer sind IT-Mitarbeiter, sie sind in ihrem Kontext eingeschlossen und dort macht es Sinn. Der Rest von uns muss das Recht des Erfinders akzeptieren, einen blauen Hund eine gelbe Katze zu nennen ;-)


2

Wie wäre es, wenn wir es von nun an Deducer nennen ? Es leitet den neuen Status basierend auf dem vorherigen Status und der eingehenden Aktion ab.


1

Sie sollten nicht als Reduzieren bezeichnet werden, da Reduzieren bedeutet, weniger zu machen. Diese Funktionen machen meistens mehr. und dann zurückgeben


1

Ich konnte nicht genau erkennen, wie ein Redux-Reduzierer direkt der Funktion zugeordnet ist, mit der Sie arbeiten. reduceHier sind einige Beispiele, um zu sehen, wie sie übereinstimmen.

Zuerst eine Standardreduzierungsfunktion (in MDN als "Akkumulator" bezeichnet) aus der MDN Array.reduce- Dokumentation und dann ein vereinfachtes Beispiel von Dan Abramov Counter.jsam Ende seines Blogposts "Möglicherweise benötigen Sie Redux nicht" .

  • sum Fügt dem Akku einen Wert hinzu
  • reducer addiert / subtrahiert einen Wert zum / vom Akkumulator.

In beiden Fällen ist der 'Zustand' hier nur eine ganze Zahl.

Sie "akkumulieren" die Aktionen in den Zustand. Dies ist auch die unveränderliche Möglichkeit, ein JavaScript-Objekt zu ändern.

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


0

Andere Antworten erklären gut, warum es so heißt, aber lassen Sie uns versuchen, mehr Dinge zu benennen ...

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

Erstens reducekönnte angerufen werden use anOperator with every action name and accumulated state, starting with origState. In Smalltalk heißt es actions inject: origState into: anOperator. Aber was spritzen Sie eigentlich in den Bediener? Der ursprüngliche Status UND die Aktionsnamen. Selbst in Smalltalk sind Methodennamen nicht sehr klar.

actionOperators[increment]ist ein Reduzierer, aber ich würde ihn lieber als actionOperator bezeichnen, da er für jede Aktion implementiert ist. Der Zustand ist nur ein Argument (und ein anderes als Rückgabewert).

Reducer ist jedoch ein besseres Wort, um über den Google-Suchergebnissen zu stehen. Es ist auch ähnlich wie Redux.


0

In diesem Code unten müssen Sie sich nur den Akkumulator als die Aktionen und currentValue als einen Status im Redux-Kontext vorstellen. In diesem Beispiel erfahren Sie, warum sie es auch als Reduzierer bezeichnen.

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

Die Methode redu () führt eine Reduzierungsfunktion (die Sie bereitstellen) für jedes Element des Arrays aus, was zu einem einzelnen Ausgabewert führt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.