Reagieren, Redux: Update Staats-und re-render-Kinder

Dem Szenario, das ich bin vor ist ich habe ein array der gespeicherten Aufträge als Redux Zustand. Ich habe einen container, der auf die Daten zugreift, mit Redux verbinden und verwendet parameter aus dieser.Requisiten.params an dann finden Sie den passenden Job, um dann die hand nach unten, um es den Kindern als eine requisite.

Innerhalb der Untergeordneten Komponente der Job löst eine Aktion aus, welche updates der job-und dann zusammengeführt wird und die updates auf die Arbeitsplätze in der Filiale. Dies scheint zu funktionieren gut, aber wenn der container neu gerendert, das Kind nicht. Ich kann sehen, das hat etwas mit der Tatsache zu tun, dass ich nicht speichern job als Requisiten oder Staat.

Meine Frage ist, was ist die beste (wiedermal)Weg, dies zu behandeln?

So, wenn ich eine änderung JobShow, jobs zu integrieren={jobs} es neu gerendert, die als Arbeitsplätze aktualisiert. Dies scheint darauf hinzudeuten, dass der Zustand ist nicht mutiert, ich kann auch bestätigen, dass der container selbst neu gerendert, und auch re-runs renderView() ist aber nicht neu Rendern JobShow.

Container:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import JobShow from './job_show';


class JobContainer extends Component {
  constructor(props){
    super(props);
  }

  renderView(job, customer){
    let viewParam = this.props.params.view;
    switch(viewParam){
      case "edit": return <JobEdit customer={customer} job={job}/>
      case "notes": return <JobShow customer={customer} activeTab={"notes"} job={job}/>
      case "quote": return <JobShow customer={customer} activeTab={"quote"} job={job}/>
      case "invoice": return <JobShow customer={customer} activeTab={"invoice"} job={job}/>
      default: return <JobShow customer={customer} activeTab={"notes"} job={job}/>
    }
  }
  render() {
    let { jobs, customers } = this.props;

    if (jobs.length < 1 || customers.length < 1){
      return <div>Loading...</div>;
    }
    let job = jobs.find(jobbie => jobbie.displayId == this.props.params.jobId);
    let customer = customers.find(customer => customer._id.$oid == job.customers[0]);

    return (
      <div className="rhs">
        {this.renderView(job, customer)}
      </div>
    );
  }
}
JobContainer.contextTypes = {
  router: React.PropTypes.object.isRequired
};
function mapStateToProps(state) {
  return  { 
    jobs: state.jobs.all,
    customers: state.customers.all
  };
}

export default connect(mapStateToProps, actions )(JobContainer);

Reducer Snippet:

import update from 'react-addons-update';
import _ from 'lodash';

export default function(state= INITIAL_STATE, action) {
  switch (action.type) {
    case FETCH_ALL_JOBS:     
      return { ...state, all: action.payload, fetched: true };

    case UPDATE_JOB_STATUS:

      let newStatusdata = action.payload;

      let jobToUpdate = state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId);
      jobToUpdate.status = newStatusdata.newStatus;
      jobToUpdate.modifiedAt = newStatusdata.timeModified;

      let updatedJobIndex = _.indexOf(state.all, state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId));
      let updatedState = update(state.all, {$merge: {[updatedJobIndex]: jobToUpdate}});

      return { ...state, all: updatedState}
  • Wenn nichts anderes, es sieht aus wie du bist mutierend Ihrem Staat mit den Linien jobToUpdate.status = ..... Zufällige mutation ist fast immer der Grund für Komponenten, die nicht re-Rendern. Siehe redux.js.org/docs/FAQ.html#react-not-rerendering. Auch, was die Arbeitsplätze und Ihren ursprünglichen Zustand Aussehen?
  • Also, wenn ich das ändern JobShow, jobs zu integrieren={jobs} es neu gerendert, die als Arbeitsplätze aktualisiert, aber die übergabe der Requisiten das Kind tut nicht Bedarf zu sein scheint, der falsche Weg. Dies scheint darauf hinzudeuten, dass der Zustand ist nicht mutiert, ich kann auch bestätigen, dass der container selbst neu gerendert, und auch re-runs der renderView Funktion aber einfach nicht re-Rendern JobShow.
  • Sie sehen, dass mehr code helfen könnte, aber Ihr jobToUpdate Linien in der reducer-snippet direkt mutiert, das job-Objekt, anstatt einer Kopie nur die Kopie ändern und zurück kopieren. Also ja, wenn du versuchst zu gehen, dass job-Objekt selbst an eine untergeordnete Komponente, die als requisite, die Referenz selbst nicht geändert hat und die Kind-Komponente wird nicht aktualisiert.
  • Ich dachte, ich hätte das mutierend Zustand Problem gelöst mit $merge aus reagieren-addons-update, auch jobs intialized als ein leeres array [].
  • Großen Dank @markerikson. Sie waren absolut richtig!!!!
  • Lasst uns einfach sagen, dass es ein sehr guter Grund, warum ich fügte hinzu, das Element der FAQ 🙂 Da bin ich mir nicht sicher, ich habe gesehen, dass problem, wo der Grund waren nicht mit mutation. Faustregel: wenn Sie jemals ein = in Ihrem reducer, und die linke Seite der Behauptung ist nicht etwas, das Sie explizit kopiert, Sie sind mutiert. Methoden wie Array.push() sind auch Häufig Täter.

InformationsquelleAutor Dom Hede | 2016-06-27



2 Replies
  1. 1

    Sieht aus wie Sie es herausgefunden selbst, aber Sie können feststellen, eine leichte Umgestaltung verbessert die Klarheit, was Sie tun. Hier sind einige Beispiele, wie Sie möglicherweise ändern Sie die Struktur Ihrer Reduzierstücke mit dem Objekt zuweisen Betrieb:

    case ActionTypes.EDIT_TODO:
      return Object.assign({}, 
        state, 
        { text: action.text }
      )

    Aus: https://github.com/mjw56/redux/blob/a8daa288d2beeefefcb88c577a7c0a86b0eb8340/examples/todomvc/reducers/todos.js

    Es gibt noch mehr in der offiziellen redux docs als auch (redux.js.org/docs/recipes/UsingObjectSpreadOperator.html)

    Vielleicht finden Sie auch das schreiben von tests und die Verwendung eines Pakets wie deepFreeze nützlich, da es wird Ihnen sagen, werfen einen Fehler, wenn Sie versehentlich mutieren Zustand, ohne es zu merken.

  2. 1

    Das problem wie schon in den Kommentaren von @markerikson war, dass ich mutierend Zustand. Mit dem $ – set-Funktion aus reagieren-addons-update habe ich erfolgreich die Inhalte aktualisiert.

    Den neuen reducer-snippet sieht wie folgt aus:

    case UPDATE_JOB_STATUS:
    
      let newStatusdata = action.payload;
    
      let jobToUpdate = state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId);
      let updatedJob = update(jobToUpdate, {status:{$set: newStatusdata.newStatus}})
      updatedJob = update(updatedJob, {modifiedAt:{$set: newStatusdata.timeModified}})
    
      let updatedJobIndex = _.indexOf(state.all, state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId));
      let updatedState = update(state.all, {$merge: {[updatedJobIndex]: updatedJob}});
    
      return { ...state, all: updatedState}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.