2017-01-01 5 views
0

Situation Ich habe eine reactjs App mit Redux. Ich habe einen Container und eine Präsentationskomponente. Meine Darstellungskomponente rendert ein Formular mit einem Array von einfachen Texteingabefeldern, und ich übergebe eine Callback-Funktion 'onChange' vom Container an die Präsentationskomponente, die eine Aktion zur Änderung des Redux-Status bei Eingabe eines der Textfelder absetzt .reactjs Präsentation comopnent nicht neu Rendern auf redux Zustandswechsel

Problem Die Präsentationskomponente macht erfolgreich die richtigen Werte für die Textfelder von redux Zustand, wenn die Halterungen Präsentationskomponente, aber nicht aktualisiert, wenn ich in den Feldern eingeben. Wenn ich die Requisiten, die an die Präsentationskomponente in mapStateToProps in dem Container übergeben werden, protokolliere, kann ich sehen, dass die OnChange-Funktion ordnungsgemäß in dem Speicher ausgeführt wird, und der Redux-Status wird korrekt aktualisiert. Die Präsentationskomponente wird jedoch in diesem Fall nicht erneut gerendert. Wenn Sie also das Textfeld eingeben, wird die Ansicht nicht aktualisiert (die Eingabe macht nichts).

formConnector

import { connect } from 'react-redux' 
    import Form from '../components/Form' 
    import { changeElementValue } from '../actions/actions' 

    const mapStateToProps = (state) => { 
     //e.g. state.elements = [{id:"email", value:"[email protected]"}] 
     let props = { 
      elements: state.elements, 
     } 

     //state and props.elements.{id}.value changes successfully when I 
     //type in one of the input fields, but 
     //the the Form component is not re-rendered 
     console.log(props) 

     return props 
    } 

    const mapDispatchToProps = (dispatch) => { 
     return { 
      onElementChange: (id, value) => { 
       dispatch(changeElementValue(id, value)) 
      }, 
     } 
    } 

    export default connect(mapStateToProps, mapDispatchToProps)(Form) 

Formular Minderer

function formReducer(state = initialState, action = null) { 
     switch(action.type) { 
      case types.CHANGE_ELEMENT_VALUE: 
       let newState = Object.assign({}, state) 
       newState.elements[action.id].value = action.value 
       return newState 

      default: 
       return state; 
     } 
    } 

Aktionen

import * as types from './actionTypes' 

    export function changeElementValue(id, value) { 
     return { type: types.CHANGE_ELEMENT_VALUE, id, value } 
    } 
+0

Können Sie den Komponentencode und die Minderer anschließen? Bist du sicher, dass sich der Laden geändert hat? Es scheint, als ob der Wert, den du nimmst, auf den state.textField.value gesetzt wird, und ich bin nicht sicher, was der Reducer ändert (über ID und welche ID er passiert). Ich wette, das Problem ist in diesem Bereich – Kinnza

+0

@Kinnza Danke für einen Blick. Ich habe das schreckliche Gefühl, dass ich das Problem maskiert habe, um den Code für diesen Beitrag zu vereinfachen. Mein Connector verbindet tatsächlich eine 'Form'-Komponente, die eine Reihe von Textelementen rendert. So enthält state ein Array von ID-Wert-Paaren. Ich werde versuchen, das Beispiel mit Code zu überarbeiten, der so einfach ist, dass er hier eingefügt werden kann, aber ich kann ihn ausführen, um sicherzustellen, dass das Problem repliziert wird. In der Zwischenzeit - ist es denkbar, dass meine Komponente die Zustandsänderung nicht erkennt, weil es sich um einen Wert handelt, der in einem Array innerhalb des Zustands verborgen ist? Sollte unveränderlich sein? – xanld

+0

OK, ich hatte noch keine Chance, einen Prototyp mit meinem vereinfachten Code zu erstellen (wird später bei Bedarf versuchen), aber ich habe das Beispiel aktualisiert, damit es repräsentativer für das ist, was in meiner echten App passiert. Jetzt gibt es ein Array von Elementen, die gerendert werden. Noch einmal, was halten Sie von meiner Vermutung, dass die Präsentationskomponente (Form) nicht erneut gerendert wird, weil sie die Zustandsänderung nicht erkennt, wenn einer der Werte im Elementarray aktualisiert wird? – xanld

Antwort

1

Wie in den Kommentaren diskutiert, ist dieser ist aufgrund von Mutation.

Versuchen Sie, Minderer Code wie folgt ändern: elegant

case types.CHANGE_ELEMENT_VALUE: { 
    const newElements = state.elements.map(function(el, index) { 
     return action.id === index 
      ? Object.assign({}, el, { value: action.value }) 
      : el; 
    }); 
    return Object.assign({}, state, { elements: newElements); 
} 

oder mehr:

case types.CHANGE_ELEMENT_VALUE: 
    return { ...state, elements: state.elements.map((el, index) => (
     action.id === index ? { ...el, value: action.value } : el 
    )} 
+0

Hallo, ich habe dies als Antwort markiert, weil es meine Frage beantwortet. Das Grundproblem, von dem dieser Zustand zurückkehrte, enthielt Hinweise auf den alten Zustand, so dass er nicht reagierte und keine Änderung feststellte. Diese Antwort hat mir geholfen, dies zu erkennen, und ich bin OB3 Kinnza und Assan sehr dankbar. Tatsächlich habe ich meine Codebeispiele verpfuscht und mein Problem bleibt bestehen, da ich die Lösung hier nicht direkt auf meinen eigentlichen Code anwenden kann. Also habe ich das Problem in einem neuen Beitrag hier genauer umrahmt: http://stackoverflow.com/questions/41418623/change-value-deep-in-redux-state. Danke noch einmal. – xanld

Verwandte Themen