2016-06-29 44 views
3

Also ich habe zwei Eingabefelder:Wie wird der Zustand eines Objekts richtig aktualisiert (ReactJS + Redux)?

<TextField onChange={this.handleUserUsername.bind(this)} 
    value={this.props.userInfo.username} 
    /> 

    <TextField onChange={this.handleUserEmail.bind(this)} 
    value={this.props.userInfo.email} 
    /> 

einmal eingegeben, würde Ich mag sie im Zustand eines Objekts speichern namens ‚userinfo‘, etwa so:

handleUserUsername(event){ 
    this.props.actions.updateUsername(event.target.value) 
    } 

    handleUserEmail(event){ 
    this.props.actions.updateEmail(event.target.value) 
    } 

und die Aktion Schöpfer sind:

updateUsername: function(eventValue){ 
    return { 
     type: 'UPDATE_USERNAME', 
     username: eventValue 
    } 
    }, 

    updateEmail: function(eventValue){ 
    return { 
     type: 'UPDATE_USERNAME', 
     email: eventValue 
    } 
    } 

und das Reduzierstück ist:

function(userInfo={}, action){ 
    switch(action.type){ 
    case 'UPDATE_USERNAME': 
     return { 
     username: action.username 
     } 

    case 'UPDATE_EMAIL': 
     return { 
     email: action.email 
     } 

Sobald Text in den Benutzernamen TextField eingegeben wurde, zeigt er an, was im TextField eingegeben wurde und speichert 'Z' für den 'Benutzernamen' und protokolliert Folgendes (im Beispiel wurde 'Z' eingegeben):

enter image description here

Dann, wenn ein Text, ‚M‘ in diesem Beispiel in die E-Mail TextField- eingegeben wird, wird der Benutzername Zustand ‚undefiniert‘, wenn es als Z bleiben soll, und E-Mail-Zustand nicht einmal gespeichert ist:

enter image description here

Im Protokoll für das Beispiel, was ich hoffe, zu sehen ist:

userInfo: Object 
    username: "Z" 
    email: "M" 

Und ich bin mit dem folgenden Status und Aktionen zur Verfügung:

function mapStateToProps(state) { 
    return state 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    actions: bindActionCreators(actions, dispatch) 
    } 
} 

Warum es die Speicherung korrekt ist nicht die Zustand für das Objekt 'userInfo'? Was wäre der richtige Weg, um ein solches Objekt zu aktualisieren? Schließlich möchte ich das 'userInfo'-Objekt in einem Array namens Benutzer speichern, wo es alle Benutzerinformationen speichern würde.

EDIT **

Als ich 'q' in den Benutzernamen Textfeld eingegeben, werden die folgenden Shows:

enter image description here

Dann, wenn ich eingeben 'M' im Passwort Textfeld, die beide nicht definiert werden jetzt:

enter image description here

EDIT 2 **

Antwort

0

Ich denke, das Problem besteht darin, dass Sie aktuelles Statusobjekt erstellen, das nur Informationen über geänderte Felder enthält. Aufgrund eines der Redux principles sollte sein Zustand unveränderlich sein und jedes Mal, wenn Sie es aktualisieren möchten, sollten Sie neues Zustandsobjekt mit den erforderlichen Änderungen erstellen.

In Ihrem Fall sollten Sie beide Felder zurück, wenn neue Statusobjekt zu schaffen (auch wenn einer von ihnen nicht ändern):

function(userInfo={}, action){ 
    switch(action.type){ 
    case 'UPDATE_USERNAME': 
    return { 
     username: action.username, 
     email: userInfo.email  // userInfo is current state, we should save old value 
    } 

    case 'UPDATE_EMAIL': 
    return { 
     username: userInfo.username, // userInfo is current state, we should save old value 
     email: action.email  
    } 

Damit Sie neuen Staat schaffen, die Felder enthält, die nicht tat geändert wird (mit gleichen Werten) und Felder, die (mit neuen Werten) geändert

EDIT:

weitere Beispiele:

davon ausgehen, dass Zustand Ihrer Anwendung ist die folgende:

oldState = { 
    email: "oldValue", 
    userName: "oldValue" 
} 

Dann, wenn Sie E-Mail zu ändern versuchen, Sie Minderer Objektzustand in der folgenden Art und Weise zurückgeben sollte:

return Object.assign({}, oldState, { 
    email: "newValue" 
}) 

-Code über neue Zustand erzeugen Objekt basiert auf dem alten Zustand und ändert das E-Mail-Attribut in dem neuen Zustand. Object.assign

Als Ergebnis Ihr neuer Zustand wird wie folgt aussehen:

{ 
    email: "newValue", 
    userName: "oldValue"  
} 

In Ihrem Beispiel Ihres Minderer Rückkehr Statusobjekt wie folgt aus:

{ 
    email: "newValue", 
} 

So ist die redux nicht, welche aktuellen Wert verstehen kann Benutzername ist.

+0

ich die Original-Beitrag unter EDIT aktualisiert ** mit neuen Protokollen. Es zeigt jetzt die Objektstatus-E-Mail an, aber beide werden undefiniert, sobald das zweite Textfeld irgendwelche Texte erhält. –

+0

Aber meine Antwort ist immer noch aktuell für Sie, wie auch @ElodSzopos unten erwähnt, in Reducer sollten Sie das gesamte Statusobjekt (einschließlich E-Mail, Benutzername, Passwort) jedes Mal, wenn Sie Änderungen durch Aktionen – muphblu

+0

Ich versuchte die Implementierung als solche wie ich zur Verfügung gestellt in EDIT 2 **, aber den folgenden Fehler erhalten: Unerwarteter Token (5: 8) bei, wo '...' beginnt, und kann nicht herausfinden, was los ist. –

1

In Ihrem Beispiel haben Sie übersehen, dass Sie den vorhandenen Status zusammen mit den Änderungen, die als Ergebnis Ihrer Aktion eingetreten sind, zurückgeben und den vorherigen Status ändern sollten.

Dies ist, was ein Reduktions tut:

Actions describe the fact that something happened, but don’t specify how the application’s state changes in response. This is the job of a reducer.

Was Sie tun müssen, ist, immer einen neuen Zustand Objekt zurück, das das Ergebnis der Anwendung Ihres Minderer auf den alten Zustand Objekt für die jeweilige Aktion ist, was geschehen .

Statt

case 'SOME_ACTION_TYPE': 
    return { 
    someProperty: 'theNewValue' 
    } 

Was sollten Sie tun, ist:

case 'SOME_ACTION_TYPE': 
    return { 
    ...state, // notice how I create a new object, but preserve all of the old 
    propertyThatIChangedInMyReducer: 'theNewValue' // this will override the old 
    } 

Grundsätzlich Sie die Minderer nehmen, gelten die Änderungen, die Sie würde für die spezifische Aktion, die dieses neue Objekt passiert ist und das Rück , die auch den anderen Teil des Zustandsbaums enthält, der unverändert geblieben ist. Du hast es versäumt, den anderen Teil zurückzugeben.

Wenn wir sagen, dass Sie auch ein Passwort-Feld hatte, dass man auf eine ähnliche Art und Weise behandeln würde, würden Sie so etwas tun:

case 'UPDATE_PASSWORD': 
    return { 
    ...state, //preserve current state, apply changes to it below 
    password: action.password, 
    }; 
+0

Vielen Dank für die Aufklärung! Ich nahm Ihren Rat und versuchte es zu implementieren, im ursprünglichen Beitrag EDIT 2 ** zur Verfügung gestellt, aber den folgenden Fehler erhalten: Unerwarteter Token (5: 8) bei, wo '...' beginnt, und kann nicht herausfinden, was los ist . –

+0

Es bedeutet, dass Sie ES6 dann nicht verwenden. Ich empfehle Ihnen dringend, zur Verwendung zu wechseln, da die meisten Beispiele und Quellen, die Sie auf React und Redux finden, es verwenden werden. Wenn Sie dies nicht können oder möchten, können Sie 'Object.assign' verwenden, um die alten Attribute beizubehalten, die in Ihrem Status unverändert bleiben. –

+0

Ich würde ES6 bevorzugen, wenn das der Fall ist. Gibt es eine Möglichkeit zu sagen, welche Version ich verwende? Scheint so, als ob das '...' in einigen Fällen funktioniert, aber nicht in anderen, also möchte ich bestätigen. Wie gehe ich auch auf ES6 um? –

Verwandte Themen