2016-12-04 2 views
0

Zuerst möchte ich erwähnen, dass das einzige, was ich zwischen zwei Ansätze ändern, ist SetState vs durch den Redux-Shop. Nichts anderes ändern, d. H. Komponenten usw.setState funktioniert aber redux store update nicht

Wenn ich den setState-Ansatz verwende, kann ich mein Modal schließen, aber wenn ich durch den Store gehe, wird es nicht geschlossen. Irgendeine Idee warum?

Hier ist mein Minderer:

import 'babel-polyfill'; 
import * as types from '../actions/actionTypes'; 

const initialState = { 
    modals: { 
     "modal1": { isDisplayed: true }, 
     "modal2": { isDisplayed: false } 
    } 
}; 

export default (state = initialState, action) => { 

    switch (action.type) { 

     case types.SET_IS_DISPLAYED_MODAL : 
      return Object.assign({}, state, { 
       modals: action.modals 
      }) 

     default: return state 
    } 
    } 
} 

Hier sind die beiden Versionen meiner onClick Aktion sind, die die modalen schließen soll.

Dies ist die setState Version und es funktioniert:

displayModal(modalId, value) 
{ 
    let modals = this.props.modals; 
    modals[modalId].isDisplayed = value; 
    return setState({modals: modals}); 
} 

Und hier ist die Version, die durch die redux Laden geht und es meine modalen schließt nicht.

displayModal(modalId, value) 
{ 
    let modals = this.props.modals; 
    modals[modalId].isDisplayed = value; 
    return this.props.actions.displayModal(modals); 
} 

gibt es nicht viel zu der Aktion, aber hier ist es:

export const displayModal = (modals) => { 
    return { 
     type: types.SET_IS_DISPLAYED_MODAL, 
     modals 
    }; 
} 

Nur damit Sie sehen, wie es in meiner Komponente sieht, hier ist es:

render() { 

    return(
    <div> 
     <div>Some info...</div> 
     {this.props.modals["modal1"].isDisplayed 
     ? <Modal1 /> 
     : null} 

     {this.props.modals["modal2"].isDisplayed 
     ? <Modal2 /> 
     : null} 
    </div> 
); 
} 

BTW, ich Ich weiß, dass ich die Action und den Reducer treffe. Ich weiß auch, dass, wenn ich einen Debugger in meine mapStateToProps lege, ich es mit aktualisiertem Zustand für meine Modale treffe. Also weiß ich, dass sowohl die Aktion als auch der Reducer tun, was sie tun sollen.

UPDATE: Ich habe gerade etwas versucht und das Problem behoben. Ich habe letzte Zeile zu mapStateToProps und den Abschnitt in meiner Komponente aktualisiert:

function mapStateToProps(state) { 

    return { 
     modals: state.modals, 
     isModal1Displayed: state.modals["modal1"].isDisplayed // Just added this line 
    } 
} 

Und änderte den Code in meiner Komponente:

render() { 

    return(
    <div> 
     <div>Some info...</div> 
     {this.props.isModal1Displayed 
     ? <Modal1 /> 
     : null} 
    </div> 
); 
} 
+0

könnten Sie den Teil Ihres Codes hinzufügen, wo Sie die Komponente verbinden – diedu

+0

Just updated the original post. Anstatt dies zu überprüfen.props.modals ["modal1"]. IsDisplayed, habe ich eine neue Requisite dafür in mapStateToProps erstellt. Ich denke, es sieht in MapStateToProps etwas funky aus, aber es funktioniert gut. Irgendeine Idee, warum der ursprüngliche Code fehlschlug? – Sam

Antwort

1

Zu allererst nie Zustand in Redux Minderer mutieren - Es muss eine reine Funktion sein, um Änderungen korrekt auszuführen und zu erkennen. Die gleichen Regeln gelten für Objekte, die Sie mit Requisiten erhalten.

Sie müssen Ihren Code ändern, damit Sie nur eine Aktion an den Store senden und ihn auf einen neuen Status reduzieren.

Zuerst Versand eine Aktion:

displayModal(modalId, value) 
{ 
    this.props.actions.displayModal(modalId, value); 
} 

Ihre Aktionsinformation tragen, die modal oder Show zu verbergen:

export const displayModal = (modalId, value) => { 
    return { 
     type: types.SET_IS_DISPLAYED_MODAL, 
     modalId, 
     value 
    }; 
} 

Dann können Sie es reduzieren:

export default (state = initialState, action) => { 
    switch (action.type) { 
     case types.SET_IS_DISPLAYED_MODAL : 
      return Object.assign({}, state, 
      { 
       modals: Object.assign({}, state.modals, 
       { 
        [action.modalId]: { isDisplayed: action.value } 
       }) 
      }) 

     default: return state 
    } 
} 

Wie Sie können sehen, dass es hier eine Menge Boilerplate gibt. Mit ES6 und ES7 können Sie Ihren Reducer mit object spread operator umschreiben, oder Sie können Immutable.js library verwenden, was Ihnen beim Festlegen von Eigenschaften tief in der Hierarchie hilft.

Reducer mit dem Objekt Spread Operator sieht wie folgt aus:

export default (state = initialState, action) => { 
    switch (action.type) { 
     case types.SET_IS_DISPLAYED_MODAL : 
      return { 
       ...state, 
       modals: { 
        ...state.modals, 
        [action.modalId]: { isDisplayed: action.value } 
       } 
      } 

     default: return state 
    } 
} 

Sie mögen sich fragen, warum Ihre Fehlerbehebung funktioniert. Lassen Sie mich erklären. Sie ändern einen modalen Status, wenn Sie eine Aktion an den Redux senden, indem Sie den Status modals[modalId].isDisplayed = value mutieren. Danach wird die Aktion ausgelöst, reduziert und mapToProps wird erneut aufgerufen. Es gibt wahrscheinlich Referenz-Check in connect Komponente höherer Ordnung und Sie haben die modal mutiert aber nicht das modals Objekt, so dass es die gleiche Referenz = Ihre Komponente hat nicht wieder rendern. Wenn Sie ein Feld isModal1Displayed hinzufügen, werden Optimierungen tatsächlich deaktiviert, da ein boolescher Vergleich, keine Referenzprüfung und Ihre Komponentenwiedergaben vorhanden sind.

Ich hoffe, es wird Ihnen helfen, Redux und seine Prinzipien zu verstehen.

+0

Ich bin eigentlich ein bisschen verwirrt. Ich verstehe und stimme dem ersten Teil Ihrer Antwort zu. Wenn ich durch den Redox-Laden gehe, mutiere ich den Zustand überhaupt nicht - wie Sie in meinem Reducer-Code sehen können. Ich habe den zweiten Teil Ihrer Antwort ein paar Mal gelesen, wo Sie darüber gesprochen haben, warum meine Lösung funktioniert, aber ich konnte Ihren Standpunkt nicht verstehen. Der einzige Unterschied ist, dass ich in meinem Update den isDisplayed-Wert von modal1 einem neuen Prop in mapStateToProps zuweist, anstatt auf seinen Wert (this.props.modals [modal1] .isDisplayed) innerhalb der Komponente zuzugreifen. In beiden Fällen wird der Wert vom modals-Objekt abgerufen. – Sam

+0

Forts. Die Tatsache, dass ich in beiden Ansätzen meinen Wert von den Modalwerten ziehe, sagt mir, dass mein Action/Reducer-Code gut funktioniert und den Status von Modals erfolgreich aktualisiert. Ich bin nur nicht sicher, warum ich nicht auf isDisplayed für modal1 mit this.props.modals [modal1] .isDisplayed in meiner Komponente zugreifen kann. – Sam

+1

Es ist schwer zu erklären, weil es erfordert, dass die Redux-Interna funktionieren, insbesondere die "connect" -Komponente. Du mutierst den Zustand in 'displayModal' durch' modals [modalId] .isDisplayed = value; 'und weil' modals' ein Objekt ist, das immer noch auf denselben Speicherort zeigt/verweist. Später, wenn Ihre Aktion verarbeitet wird, versucht Redux, Ihre Komponente erneut zu rendern, sieht aber 'modals' ===' modals' und tut in diesem Fall nichts. Aus diesem Grund wurde Ihre Komponente nicht aktualisiert. –