2016-03-25 12 views
20

In Redux kann ich leicht Änderungen abonnieren speichern mitabonniere einzelne Eigenschaftsänderung im Speicher in Redux

store.subscribe(() => my handler goes here) 

Aber was, wenn mein Speicher voll von verschiedenen Objekten ist und an einem bestimmten Ort in meinem app ich will Änderungen abonnieren, die nur in einem bestimmten Objekt im Geschäft vorgenommen wurden?

Antwort

45

Es gibt keine Möglichkeit, einen Teil der Speicher zu unterzeichnen, wenn subscribe direkt verwenden, sondern als der Schöpfer von Redux selbst sagt - don't use subscribe directly! Für den Datenfluss eines Redux App wirklich zu arbeiten, werden Sie eine Komponente mögen, dass hüllt Ihre gesamte App Diese Komponente wird Ihr Geschäft abonnieren. Der Rest Ihrer Komponenten ist für diese Wrapper-Komponente untergeordnet und erhält nur die Teile des Zustands, die sie benötigen.

Wenn Sie Redux mit React verwenden, dann gibt es gute Nachrichten - das offizielle react-redux Paket kümmert sich darum! Es stellt diese Wrapper-Komponente bereit, die <Provider /> genannt wird. Sie haben dann mindestens eine "Smart-Komponente", die Statusänderungen abgehört, die von Provider aus dem Laden weitergegeben werden. Sie können angeben, auf welche Teile des Zustands er hören soll, und diese Teile des Staates werden als Requisiten an diese Komponente weitergegeben (und dann kann er diese natürlich an seine eigenen Kinder weitergeben). Sie können dies festlegen, indem Sie die Funktion connect() für Ihre "intelligente" Komponente verwenden und die mapStateToProps-Funktion als ersten Parameter verwenden. Zur Erinnerung:

Wrap Wurzelkomponente mit Provider Komponente, die speichern abonniert ändert

ReactDOM.render(
    <Provider store={store}> 
    <App /> 
    </Provider>, 
    document.getElementById('root') 
) 

Jetzt jedes Kind von <App />, die mit connect() wird eine „intelligente“ Komponente gewickelt ist. Sie können mapStateToProps weitergeben, um bestimmte Teile des Staates auszuwählen und diese als Requisiten zu geben.

const mapStateToProps = (state) => { 
    return { 
     somethingFromStore: state.somethingFromStore 
    } 
} 

class ChildOfApp extends Component { 
    render() { 
     return <div>{this.props.somethingFromStore}</div> 
    } 
} 

//wrap App in connect and pass in mapStateToProps 
export default connect(mapStateToProps)(ChildOfApp) 

Offensichtlich <App /> können viele Kinder haben, und Sie können, welche Teile des Staates wählen, und wählen die mapStateToProps zu für jedes seiner Kinder hören sollte. Ich würde empfehlen, die Dokumente unter usage with React zu lesen, um diesen Fluss besser zu verstehen.

+3

Vielen Dank für so detaillierte Antwort –

+0

Das ist großartig. Ich hätte gerne eine Komponente, um auf eine Aktion zu reagieren. Nehmen wir an, es gibt eine Komponente 'NavBar', die eine Aktion' toggleDrawer' absetzt. Diese Aktion speichert einen Wert im Speicher, der den Status der Schublade 'isDrawerOpen' darstellt. Dann, wie mache ich die Schublade geöffnet, wenn die Aktion gesendet wird? Auch hier gibt es einen möglichen Konflikt: die Schublade selbst kann geöffnet werden und sie steuert ihre 'offene' Eigenschaft, so dass' isDrawerOpen' aus der Schublade ändert, würde eine Endlosschleife verursachen ... – Miquel

+0

noch gibt es Code in 'connect', um darauf zu antworten Alle Änderungen und Ausführen von mindestens etwas Code vor dem Vergleich der vorherigen und nächsten Rückgabe von 'mapStateToProps', wodurch die Leistung unnötig beeinträchtigt wird. Ich frage mich nur, ob wir die Namen der gewünschten Schlüssel erkennen können, zB: 'function mapStateToProps (({someKey, anotherReducerKey}) => ...' und nur diese abonniert.In Javascript können Sie die Namen von Argumenten bekommen - also Die Frage ist, können Sie die Namen der destrukturierten Schlüssel dieser Argumente. –

7

Redux bietet nur eine allgemeine Möglichkeit, um zu wissen, wann der Speicher aktualisiert wurde: subscribe. Rückrufe zu subscribe erhalten keine Informationen darüber, was sich geändert haben könnte, da die API subscribe bewusst niedrig ist und jeden Rückruf ohne Argumente ausführt. Alles, was Sie wissen, ist, dass der Laden in irgendeiner Weise aktualisiert wurde.

Aus diesem Grund muss jemand eine spezifische Logik schreiben, um den alten Zustand mit dem neuen Zustand zu vergleichen und zu sehen, ob sich etwas geändert hat. Sie könnten dies umgehen, indem Sie React-Redux verwenden, eine mapStateToProps-Funktion für Ihre Komponente angeben, componentWillReceiveProps in Ihrer Komponente implementieren und prüfen, ob sich bestimmte Requisiten aus dem Geschäft geändert haben.

Es gibt auch ein paar Addon-Bibliotheken, die versuchen, diesen Fall zu behandeln: https://github.com/ashaffer/redux-subscribe und https://github.com/jprichardson/redux-watch. Beides erlaubt Ihnen grundsätzlich, einen bestimmten Teil des zu betrachtenden Zustands mit verschiedenen Ansätzen anzugeben.

0

Zusätzlich zu dem, was Andy Noelker sagte, übergibt mapStateToProps nicht nur einen Teil des Zustands ordnungsgemäß in Ihrem Komponentenbaum, sondern auch Änderungen, die direkt in diesen subskribierten Teilen des Staates vorgenommen wurden.

Es stimmt, dass jede mapStateToProp Funktion, die Sie an den Speicher binden, jedes Mal aufgerufen wird, wenn ein Teil des Status geändert wird, aber das Ergebnis des Aufrufs wird flach im Vergleich zum vorherigen Aufruf - wenn Top-Level-Schlüssel, die Sie abonniert haben nicht ändern (die Referenz bleibt gleich). Dann würde mapStateToProps nicht erneut rendern aufrufen. Also, wenn Sie wollen, dass das Konzept funktioniert, müssen Sie mapStateToProps einfach halten, keine Zusammenführung, Typänderungen oder irgendetwas anderes, sie sollten einfach Teile des Zustands weitergeben.

Wenn Sie beim Abonnieren die Daten aus dem Status reduzieren möchten, z. B. Listendaten im Status hatten und sie in Objekte mit IDs als Schlüssel konvertieren möchten oder mehrere Zustände in Datenstrukturen einfügen möchten, Sie sollten mapStateToProps mit createSelector aus der Bibliothek reselect kombinieren, indem Sie alle diese Änderungen innerhalb des Selektors vornehmen. Selektoren sind reine Funktionen, die Statusabschnitte reduzieren und zwischenspeichern, die als Eingabe übergeben wurden, und wenn sich die Eingabe nicht geändert hat - sie geben genau dieselbe Referenz wie beim letzten Aufruf zurück - ohne die Reduktion auszuführen.

0

Ich folge diesem Thread besser, um Nachrichten zu bekommen, weil ich es brauche.

Bisher denke ich: Aktuelle Stand & vorheriger Zustand kann als 2 Json-Objekt verwendet werden. Der Vergleich der Unterschiede zwischen zwei JSON kann uns helfen, die tatsächliche Änderung herauszufinden.

Wir können eine Funktion erstellen, um Eigenschaft Name des Staates zu übergeben, dann können wir zwei kleinere JSON-Objekt vergleichen, die einfacher und kürzere Zeit zu nehmen ist.