2016-03-21 1 views
0

Um Redux zu lernen, beginne ich eine einfache Web-Anwendung.Verschachtelte Reduzierungen

Wenn es eine "Authentifizierung" -Aktion gibt, die den Benutzernamen und das Passwort bestätigt. Ich möchte dann eine "Login" oder "Fail" -Aktion aufgerufen werden. Ich kann nicht herausfinden, wie. Ich kann den Authentifizierungsschritt aufrufen, aber der verschachtelte/folgende Aufruf wird nicht ausgeführt.

Wie ist es möglich, eine Funktion innerhalb einer anderen Funktion aufzurufen? (Das ist, wie frustrierend mein Problem läuft darauf hinaus ^^)

Mein Code sieht wie folgt aus:

function authenticateClient(state, client){ 
    if (client.password === 'perfectsec') 
     return dispatch(Actions.connectClient(client)); 
    else 
     return dispatch(Actions.refuseClient(client)); 
} 

dispatch in einem Druckminderer ist falsch. Am einfachsten wäre es, die Funktionen connectClient(state, client) oder refuseClient(state, client) direkt aufzurufen. Aber dann geht dieser Schritt nicht durch den Redux-Fluss.


Kontext Code:

/* actions.js */ 

export function authenticateClient(client) { 
    return { type: Types.authenticateClient, client }; 
} 

export function connectClient(client, isNew) { 
    return { type: Types.connectClient, client, isNew }; 
} 

export function refuseClient(client) { 
    return { type: Types.refuseClient, client }; 
} 


/* main.js */ 

/* reducer */ 
const reducer = (state = loadState(), action) => { 
    console.log(chalk.red(`*${action.type}*`)); 
    switch (action.type) { 
    case Actions.Types.authenticateClient: 
     return authenticateClient(state, action); 
    case Actions.Types.connectClient: 
     return connectClient(state, action); 
    case Actions.Types.refuseClient: 
     return refuseClient(state, action); 
    default: 
     return state; 
    } 
}; 


/* store */ 
store = createStore(reducer); 


/* app */ 
store.dispatch(Actions.authenticateClient({username, password})); 
+0

Ich bin nicht 100% in der Lage, Ihrem Code zu folgen, also nur um zu verdeutlichen - Sie versuchen nicht, Aktionen von innerhalb der Reduzierungen zu versenden, oder? Denn das ist der einzige Ort, an dem Sie zu 100% _never_ sind, um Aktionen zu versenden. –

+0

Danke. Ja, genau das versuche ich. Und mir ist aufgefallen, dass das nicht stimmt. Aber ich verstehe nicht, wie ich mein Ziel erreichen kann. Ich fügte einen Absatz hinzu und versuchte zu klären. –

+1

Wenn Sie Aktionen bedingungsabhängig absetzen müssen, sollte diese Logik höchstwahrscheinlich in einem anderen Aktionsersteller sein (zB 'Actions.connectClientIfValid (client)') - wenn die Eingabe gültig ist, geben Sie das Ergebnis von 'Actions.connectClient (client) 'zurück. Wenn nicht, geben Sie das Ergebnis von 'Actions.refuseClient (client)' zurück. Sie können dann versenden, was zurückgegeben wird. Alles, was Ihr Reducer jemals tun sollte, ist 'state + action = newState' - es sollte niemals Nebenwirkungen auf den Rest Ihrer Anwendung haben. –

Antwort

1

Reduzierungen sollten niemals Aktionen versenden, oder irgendetwas anderes tun, die Nebenwirkungen hat. Alles, was ein Reducer jemals sein sollte, ist eine reine Funktion des Zustands und der Aktionen (effektiv state + action = newState) - die gesamte Redux-Bibliothek basiert auf dieser Annahme, und ich glaube, sie ist speziell darauf ausgelegt, einen Fehler auszulösen, wenn Sie versuchen, den Dispatch innerhalb eines Reducers aufzurufen.

Der beste Weg, bedingt zu gehen über eine Aktion Dispatching ist eine neue ‚Aktion Schöpfer‘ zu schaffen - Sie ein paar von diesen in Ihrer Anwendung haben bereits:

export function authenticateClient(client) { 
    return { type: Types.authenticateClient, client }; 
} 

export function connectClient(client, isNew) { 
    return { type: Types.connectClient, client, isNew }; 
} 

export function refuseClient(client) { 
    return { type: Types.refuseClient, client }; 
} 

Beachten Sie, dass Standard-Aktion Schöpfer nicht Versende die Aktion selbst. Sie sind nur Funktionen, die zurückgeben eine Aktion, die Sie sich selbst zu einem bestimmten Zeitpunkt (das ist praktisch, wenn Sie eine Aktion erstellen und halten Sie es für eine kurze Weile, bevor es tatsächlich abschicken). Die Gewässer werden etwas matschig, sobald Sie anfangen, asynchrone Aktions-Ersteller zu schreiben, aber das liegt nicht wirklich im Bereich Ihres Problems, also werde ich es vorläufig überspringen (ich empfehle Ihnen, den Async-Abschnitt der Dokumentation zu lesen!) coole Sachen, sobald du deinen Kopf drum herum hast).

Was Sie hier ausdrücken möchten, ist eine Funktion, die besagt: "Wenn eine Bedingung erfüllt ist, geben Sie mir eine connectClient Aktion, wenn nicht, geben Sie mir eine refuseClient Aktion". Wir wissen bereits, dass eine Funktion, die Ihnen eine Aktion gibt, ein Aktionsersteller ist, der uns zum Hauptpunkt dieser Antwort führt: Action-Ersteller können die Logik haben. Während 90% von ihnen nur Daten aufnehmen und ein Objekt sofort zurückgeben, ist dies nicht die einzige Form, die sie annehmen können. Hier ist ein Beispiel dafür, wie könnte diese Funktionalität dargestellt werden:

export function connectClientIfValid(client) { 
    if (client.valid === true) { 
    return connectClient(client); 
    } 
    else { 
    return refuseClient(client); 
    } 
} 

Wieder nichts wirklich von dieser Funktion ausgelöst wird - es gibt nur eine Aktion, die Sie in Ihrer Freizeit versenden können, etwa so:

dispatch(connectClientIfValid(client)); 

Ihre Logik wird ausgeführt, und die entsprechende Aktion wird ausgeführt, ohne dass die reine/synchrone Art des Reduzierers beeinträchtigt werden muss. Alles, was Ihr Reducer tun muss, ist, die Aktionen zu lesen, wenn sie eintreffen, und den Status entsprechend zu aktualisieren - es muss sich nicht um die Logik kümmern, die die Aktionen verursacht hat.

+0

Nochmals vielen Dank für Ihre Geduld. Die Zeit wird zeigen, ob ich es wirklich verstehe. Wie Sie betonen, ist der Unterschied zwischen einem Reducer und einem Action Creator wichtig, um klar zu kommen. Was ich versuchte zu tun, ist einfach ein "Sub Reducer". Mein authenticateClient ist ein Reducer. Ich könnte ['combineReducers'] (http://redux.js.org/docs/api/combineReducers.html) für diesen Anwendungsfall verwenden. –

Verwandte Themen