2015-03-09 7 views
19

Wenn ich setState in componentWillUpdate, componentWillUpdate läuft in einer Endlosschleife, die nicht aufhören ausgelöst wird.Wie aktualisiere ich den Status (mithilfe von ReactJS), wenn ich SetState nicht in ComponentWillUpdate aufrufen soll?

Das gibt meinem render nie eine Chance, meine Änderungen widerzuspiegeln. Wie kann ich den Status ändern, wenn ich componentWillUpdate nicht verwenden soll?

Edit: Ich habe bereits einige Verständnis dafür, dass setState nicht in ComponentWillUpdate aufgerufen werden sollte. Ich bin nur verwirrt, was ich als Alternative tun sollte.

Edit # 2: Ich begann mit componentWillReceiveProps, aber ich kann nicht scheinen, diese Funktion auszulösen, wenn meine Elternkomponente den Status ändert. Ich biete diesen Zustand dem Elternteil als Requisite für mein Kind an.

Antwort

25

Als erstes sollten Sie die offizielle Dokumentation für diese Methode (link) prüfen. Wo können Sie lesen, wenn die Funktion tatsächlich aufgerufen wird.

Lesen Sie dann häufiger Fehler (Anmerkung):

Sie können nicht verwenden this.setState() in diesem Verfahren. Wenn Sie den Status als Reaktion auf eine Prop-Änderung aktualisieren müssen, verwenden Sie stattdessen componentWillReceiveProps.

Sie ändern den Status und Reagieren automatisch ruft componentWillUpdate.

+0

Danke! Ich habe die Dokumente gelesen, aber die Idee von Requisiten und Zuständen, die componentWillUpdate auslösen, nicht verstanden. Eigentlich wollte ich componentWillUpdate aufrufen, weil ich neue Requisiten von einem Elternteil erhalte. Ich möchte jedoch die Daten in den Requisiten verarbeiten, bevor ich meine Daten rendern lasse. Bedeutet das, dass ich setState nicht aufrufen muss und die Requisiten nur direkt manipulieren muss? – hdavidzhu

+0

@David, ändern Sie Kinder Requisiten nach der Montage sie auf die Dom? Du solltest Requisiten niemals direkt manipulieren, da sie kein Requisiten-verändertes Ereignis auslösen. – zaynetro

+0

Ich habe so etwas wie dies: ''

This room is currently {this.props.roomId}

Die 'this.state.queue' verändert, aber mein Kind' SongQueue' kann nicht scheinen, um es richtig zu erhalten. Dies ist in der 'render' meiner ersten Hauptmutterkomponente. – hdavidzhu

0

Ich verstehe, dass dies in der guide gegen gewarnt wird, aber ich bin mir nicht sicher, ob ich das Problem mit dem Aufruf setState von innerhalb componentWillUpdate sehen kann. Richtig, es kann zu einer unendlichen Rekursion führen, es sei denn, liefert natürlich einen Grund für diese Rekursion (eine Möglichkeit, daraus auszubrechen). Z.B. Eine Möglichkeit könnte darin bestehen, den zweiten Parameter (nextState) in componentWillUpdate zu überprüfen und setState nicht erneut aufzurufen, wenn eine Bedingung erfüllt ist (dh wenn die Rekursion beendet ist).

Als ein minimales Beispiel stellen Sie sich eine Komponente vor, die überhaupt keine Eigenschaften hat, sondern nur zwei Zustandszustände. Stellen Sie sich weiter vor, dass das zweite Stück des Staates asynchron von dem ersten erhalten wird. Z.B. Der erste Teil des Zustands könnte ein Parameter sein, der einem Ajax-Aufruf zur Verfügung gestellt wird, und der zweite Teil des Zustands ist das Ergebnis dieses Aufrufs. Also im Grunde rufen Sie this.setState, um die Parameter zu konfigurieren und dann in componentWillUpdate können Sie so etwas wie die folgenden (Dinge einfach zu halten verwende ich ein window.setTimeout als Platzhalter für einen Ajax-Aufruf) tun:

const ComponentWithAsyncState = React.createClass({ 
    getInitialState: function() { 
     return { 
      ajaxParams: '', 
      ajaxResult: '' 
     }; 
    }, 
    setAjaxParams: function(params) { 
     this.setState({ajaxParams: params}); 
    }, 
    componentWillUpdate: function(_, nextState) { 
     if (nextState.ajaxParams!=this.state.ajaxParams) 
      window.setTimeout(function imagineThisIsAjax() { 
       this.setState({ajaxResult: `result from ${nextState.ajaxParams}`}); 
      }.bind(this), 2000); 
    }, 

Wenn (zB durch einige Steuerelemente von dieser Komponente) der ajaxParams Änderung, die Abfolge von Aktionen verwaltet werden so etwas wie (wo ~~> bezeichnet Asynchronität) sein:

setAjaxParams --> this.setState --> componentWillUpdate ~~> imagineThisIsAjax --> this.setState --> componentWillUpdate 

Ie der zweite Aufruf an componentWillUpdate wird nicht zu einem weiteren this.setState führen und somit wird die Rekursion dort enden.

+1

React Komponenten sollten wirklich nur über die Anzeige von Daten zu ihm. Deshalb haben sie Flux eingeführt, um den Datenfluss zu handhaben, und reagieren einfach nur darauf. Wenn this.setState() in der Komponente "componentWillUpdate" verwendet wird, wird in der Ansichtsebene eine Geschäftslogik ausgegeben, was in Ihrem Beispiel der Fall ist. Natürlich können Sie einfach tun, was Sie wollen, und es * funktioniert *. Aber ich glaube, dass es bessere Werkzeuge (Muster) gibt, die Sie verwenden können, ohne ein Risiko für eine Endlosschleife einzugehen. – Populus

+0

SetState auf ComponentWillUpdate zu verwenden wird nicht empfohlen, weil Anrufschleifen (https://facebook.github.io/react/docs/react-component.html#componentwillupdate) –

+0

@the_bluescreen ist mir natürlich bewusst, weshalb Ich spreche von der Möglichkeit der unendlichen Rekursion und beachte, dass Sie dieses Problem nicht haben, wenn Sie der Rekursion einen Boden geben. Anscheinend hast du die Antwort nicht gelesen oder versäumt, sie zu verstehen. Oh, und danke für den Link, aber es ist bereits in meiner Antwort. –

Verwandte Themen