React-dnd: Warnung mit verschachtelter DragSource

Erstellt am 6. Apr. 2016  ·  27Kommentare  ·  Quelle: react-dnd/react-dnd

Wenn Sie eine DragSource in einer Komponente haben, die auch eine DragSource ist (dh etwas in eine Drag-Datei ziehen), wird beim Ziehen der übergeordneten Komponente die folgende Warnung angezeigt.

Warning: setState(...): Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
warning @   modules.js?hash=107dc56…:19491
getInternalInstanceReadyForUpdate   @   modules.js?hash=107dc56…:5476
ReactUpdateQueue.enqueueSetState    @   modules.js?hash=107dc56…:5617
ReactComponent.setState @   modules.js?hash=107dc56…:15132
handleChange    @   modules.js?hash=107dc56…:20844
handleChange    @   modules.js?hash=107dc56…:22861
dispatch    @   modules.js?hash=107dc56…:23568
addSource   @   modules.js?hash=107dc56…:23124
registerSource  @   modules.js?hash=107dc56…:21172
receiveType @   modules.js?hash=107dc56…:21099
receiveProps    @   modules.js?hash=107dc56…:21089
DragSource(NestedComponent) @   modules.js?hash=107dc56…:21062
ReactCompositeComponentMixin.mountComponent @   modules.js?hash=107dc56…:6679
ReactCompositeComponent_mountComponent  @   modules.js?hash=107dc56…:896
ReactReconciler.mountComponent  @   modules.js?hash=107dc56…:5167
ReactMultiChild.Mixin.mountChildren @   modules.js?hash=107dc56…:13562
ReactDOMComponent.Mixin._createContentMarkup    @   modules.js?hash=107dc56…:10901
ReactDOMComponent.Mixin.mountComponent  @   modules.js?hash=107dc56…:10789
ReactReconciler.mountComponent  @   modules.js?hash=107dc56…:5167
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7101
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.receiveComponent   @   modules.js?hash=107dc56…:6936
ReactReconciler.receiveComponent    @   modules.js?hash=107dc56…:5217
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7093
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.receiveComponent   @   modules.js?hash=107dc56…:6936
ReactReconciler.receiveComponent    @   modules.js?hash=107dc56…:5217
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7093
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.performUpdateIfNecessary   @   modules.js?hash=107dc56…:6952
ReactReconciler.performUpdateIfNecessary    @   modules.js?hash=107dc56…:5232
runBatchedUpdates   @   modules.js?hash=107dc56…:5832
Mixin.perform   @   modules.js?hash=107dc56…:6304
Mixin.perform   @   modules.js?hash=107dc56…:6304
assign.perform  @   modules.js?hash=107dc56…:5789
flushBatchedUpdates @   modules.js?hash=107dc56…:5850
ReactUpdates_flushBatchedUpdates    @   modules.js?hash=107dc56…:896
Mixin.closeAll  @   modules.js?hash=107dc56…:6370
Mixin.perform   @   modules.js?hash=107dc56…:6317
ReactDefaultBatchingStrategy.batchedUpdates @   modules.js?hash=107dc56…:10295
enqueueUpdate   @   modules.js?hash=107dc56…:5879
enqueueUpdate   @   modules.js?hash=107dc56…:5460
ReactUpdateQueue.enqueueSetState    @   modules.js?hash=107dc56…:5626
ReactComponent.setState @   modules.js?hash=107dc56…:15132
handleChange    @   modules.js?hash=107dc56…:21121
handleChange    @   modules.js?hash=107dc56…:22861
dispatch    @   modules.js?hash=107dc56…:23568
(anonymous function)    @   modules.js?hash=107dc56…:22100
endDragIfSourceWasRemovedFromDOM    @   modules.js?hash=107dc56…:29563
handleTopDrop   @   modules.js?hash=107dc56…:29860

Ein Beispiel hierfür wäre:

class ParentDraggable extends React.Component {
    render() {
        return this.props.connectDragSource(
            <NestedDraggable/>
        );
    }
}

//... Skip the code for containers

class NestedDraggable extends React.Component {
    render() {
        return this.props.connectDragSource(
            <div></div>
        );
    }
}

Ich glaube, das Problem beruht auf der Tatsache, dass das erneute Rendern der übergeordneten Komponente dazu führt, dass der untergeordnete DragSource-Aufruf während des Funktionsaufrufs von receiveProps einen Aufruf von setState ausführt.

triage wontfix

Hilfreichster Kommentar

Nur für den Fall, dass es jemandem hilft: Ich bin darauf gestoßen, als ich eine Komponente gerendert habe, die eine Drag-Quelle in meiner benutzerdefinierten Drag-Ebene war, weil es praktisch war. Ich habe die Drag-Source-Komponente verwendet, da es sich um dieselbe Entität handelt, die ich ziehen wollte. Daher war es für mich nur sinnvoll, den Code "DRY" beizubehalten, indem ich ihn wiederverwendete. Ich habe nicht daran gedacht, dass der gesamte DragSource-Code darin enthalten ist - rückblickend möchte ich natürlich nicht, dass eine Drag-Quelle als das Ding in der benutzerdefinierten Drag-Ebene gerendert wird.

Letztendlich habe ich meine Komponente in eine "Draggable" -Version aufgeteilt, die die Basiskomponente umhüllte, und dann die Basiskomponente in meiner benutzerdefinierten Drag-Ebene verwendet. Keine Warnung mehr, besserer Code! 👍

Alle 27 Kommentare

: +1:

Können Sie bitte ein Projekt zur Reproduktion des Problems bereitstellen?

Ich versuche, ein einfaches Beispiel zu erstellen, und habe Probleme bei der Reproduktion außerhalb meines privaten Projekts, an dem ich arbeite. @nihtalak , hast du ein Repo auf Github, das das Problem verursacht?

Hier ist ein kleines Repo, das das beschriebene Verhalten zeigt: https://github.com/ebakan/react-dnd-nested-bug

Seltsamerweise löst das Component diesen Fehler nur aus, wenn es auf monitor.getItem() . Wenn es auf monitor.isDragging() wartet, funktioniert es ordnungsgemäß, wie in diesem Zweig gezeigt: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is- Schleppen

Der Fehler wird auch beim Abhören von monitor.getItemType() ausgelöst :

@ebakan - interessant. Ich frage mich, warum dieser Fehler in meinem Code auftritt, der isDragging verwendet. Ich mache einige wackelige Dinge mit dem verschachtelten Draggable, also könnte es eine Manifestation des gleichen Fehlers sein, den Sie sehen. Danke für die Hilfe beim Reproduzieren!

Ich habe auch Draggables verschachtelt, bin mir aber nicht sicher, ob das das Problem ist.
Es scheint ein neues Geschäft und den Code zu erstellen, der abgehört wird. Ich habe ein Video gemacht, wenn das hilft:
http://screencast.com/t/qCrJRPAS2MYR

Update: Ich habe das Problem gefunden. Ich hatte einen übrig gebliebenen Listener. In meinem Fall war dies nicht auf eine Reaktion zurückzuführen.
Update2: Ich habe zu früh gesprochen. Nach dem Entfernen des übrig gebliebenen Listeners wird immer noch die Warnung angezeigt.

Ich habe gerade Dnd zu einer anderen Komponente hinzugefügt und dieses Problem auch ohne verschachtelte oder mehrere ziehende Komponenten festgestellt.

Nach einigem Graben stellte ich fest, dass das Problem mit der benutzerdefinierten Drag-Ebene zusammenhängt, die die Komponente beim Ziehen rendert.

Wenn ich stattdessen Text in die zu ziehende Komponente einfüge, funktioniert dies einwandfrei. Die Komponente selbst ist die Drag-Quelle.

@jchristman @hakunin Ich habe keine verschachtelten Cannot update during an existing state transition gestoßen, als ich ein Drop-Ziel hatte, das basierend auf isDragging bedingt gerendert wurde. Könnte dies in einem Ihrer Beispiele der Fall sein? So etwas in der Art:

render() {
    var dropZone;
    if (this.props.isDragging) dropZone = <MyDropTarget />;
    return <div>
       <MyDragSource />
       {dropZone}
    </div>
}

Am Ende wurde es umgangen, indem display: none/block , um das Ziel auszublenden, anstatt die Komponente hinzuzufügen und zu entfernen, wenn das Ziehen aktiv ist.

Ich denke, das könnte das Problem sein. Ich werde es prüfen und Sie anschließend informieren. Das ist definitiv das Konstrukt, das ich gerade benutze.

Naw - Ich bekomme das Problem, wenn der "Tropfen" passiert. Dann versucht es, die Komponente erneut zu rendern und gibt diese Warnung aus.

Ich habe die gleiche Warnung erhalten, als meine Drag-Vorschau eine Komponente war, die eine DragSource war (was ich nicht tun sollte).

@jchristman hast du jemals eine Lösung dafür gefunden?

Ich arbeite mit verschachtelten DragSources und habe plötzlich diesen Fehler gesehen, als ich die verschachtelte Ressource gelöscht habe.

Ich kann ein Beispiel geben, wollte aber sehen, ob jemand das Problem gelöst oder eine geeignete Problemumgehung gefunden hat.

Ich habe die gleiche Warnung erhalten, als meine Drag-Vorschau eine Komponente war, die eine DragSource war (was ich nicht tun sollte).

Danke @arjunu meine Warnung wurde dadurch verursacht!
Ich habe diese immer noch gelegentlich, also denke ich, dass es auch einen anderen Grund gibt, der behoben werden muss. Könnte meinerseits sein :)

@ gharwood1 , ich lebe nur mit dem Problem, bis es behoben werden kann. Ich habe ein paar Stunden damit verbracht, diese Bibliothek wirklich zu verstehen, damit ich eine Lösung anfordern konnte, aber sie ist ziemlich komplex, also bin ich weitergegangen. Ich habe einfach keine Zeit ... :-(

@gaearon Ich habe noch kein Projekt erstellt, das von jemandem heruntergezogen werden kann, aber ich denke, ich kann bei Bedarf eines

Grundsätzlich ist das, was ich hier versuche, gültig:

https://github.com/arackaf/booklist/blob/react-dnd-bug-freeze/react-redux/modules/subjects/components/subjectsList-es6.js

Wenn ich die Bedingung in Zeile 64 deaktiviere, ist alles in Ordnung

if (this.props.draggingSubject){
    effectiveChildren.push(this.props.draggingSubject);
}

Sobald jedoch die Ergebnisse des Drag-Ereignisses beginnen, Requisiten zu ändern und Komponenten zu rendern, wird die obige Warnung häufig ausgespuckt.

Sollte ich das nicht tun?

Der Anwendungsfall besteht im Wesentlichen darin, eine Vorschau des aktuell gezogenen Elements im Ablageziel anzuzeigen. Das Obige ist ein Proof of Concept - noch nicht mit dem Redux-Store verbunden, da ich nicht sicher bin, ob dies überhaupt gültig ist.


Hm, es sieht so aus, als wäre es in Ordnung, wenn ich meine Änderungen lokal auf SubjectDisplayContent behalte, aber die Warnungen beginnen, wenn sich die Änderungen auf SubjectDisplay . Wenn also ein dropTarget Requisiten sendet, die ein anderes dropTarget ändern, ärgert sich reag-dnd. Wird dies erwartet und ich muss einige Dinge überdenken, oder ist dies ein Fehler mit dnd?

Ich habe genau das gleiche Problem. In einigen Situationen können Sie ein DragDropContext um jedes verschachtelte Draggable erstellen. Dies funktioniert jedoch nicht, sobald Sie einen benutzerdefinierten DragLayer möchten.

Ich habe den gleichen Fehler erhalten, außer dass ich verschachtelte dropTargets mache.
Nachdem ich mich in der Dokumentation umgesehen hatte, versuchte ich es mit

isOver (Optionen): Gibt true zurück, wenn ein Ziehvorgang ausgeführt wird und der Zeiger derzeit über dem Eigentümer schwebt. Sie können optional {flat: true} übergeben, um genau zu prüfen, ob nur der Eigentümer im Gegensatz zu einem verschachtelten Ziel schwebt.

(mit der Option "flach ist wahr") in der canDrop-Funktion des übergeordneten dropTarget, und das Problem wurde behoben. Ich würde denken, dass das gleiche auf einige andere Szenarien angewendet werden könnte.

@jchenjc Ich habe es versucht, aber es hat bei mir nicht funktioniert. Um ehrlich zu sein, ist meine Situation mit verschachtelter Drag-Vorschau + Drag-Quelle + Drop-Ziel, das über Listen hinweg funktionieren muss, äußerst kompliziert.

FWIW: Ich habe sowohl verschachtelte Drag-Quellen als auch eine benutzerdefinierte Drag-Ebene. Wenn ich die benutzerdefinierte Drag-Ebene entferne, wird die Nachricht ausgeblendet. Nach der Überprüfung des Stack-Trace scheint das Problem hier zu liegen:

printWarning    @   warning.js?8a56:36
warning @   warning.js?8a56:60
getInternalInstanceReadyForUpdate   @   ReactUpdateQueue.js?6531:54
enqueueSetState @   ReactUpdateQueue.js?6531:200
ReactComponent.setState @   ReactComponent.js?702a:63
handleChange    @   DragLayer.js?1cbc:124 <--------------
handleChange    @   DragDropMonitor.js?0588:60

Relevanter Code ist hier . Ich werde untersuchen, warum der Status in meinem Fall anders sein könnte, um ein erneutes Rendern auszulösen ...

Mit einer Dragsource + Droptarget, die in einem Droptarget verschachtelt ist, tritt dieses Problem auf.

Ein Grund dafür ist, dass Gaearon sich vorstellte, Listen per Drag & Drop zu erstellen, indem jedes Listenelement zu einem Drop-Ziel gemacht wurde, anstatt die Listenkomponente zu einem einzelnen Drop-Ziel zu machen, das anhand der Drag-Hover-Position festlegt, was zu tun ist. Der letztere Weg ist, wie die meisten anderen DnD-Systeme, die ich gesehen habe, Dinge tun.

Nur für den Fall, dass es jemandem hilft: Ich bin darauf gestoßen, als ich eine Komponente gerendert habe, die eine Drag-Quelle in meiner benutzerdefinierten Drag-Ebene war, weil es praktisch war. Ich habe die Drag-Source-Komponente verwendet, da es sich um dieselbe Entität handelt, die ich ziehen wollte. Daher war es für mich nur sinnvoll, den Code "DRY" beizubehalten, indem ich ihn wiederverwendete. Ich habe nicht daran gedacht, dass der gesamte DragSource-Code darin enthalten ist - rückblickend möchte ich natürlich nicht, dass eine Drag-Quelle als das Ding in der benutzerdefinierten Drag-Ebene gerendert wird.

Letztendlich habe ich meine Komponente in eine "Draggable" -Version aufgeteilt, die die Basiskomponente umhüllte, und dann die Basiskomponente in meiner benutzerdefinierten Drag-Ebene verwendet. Keine Warnung mehr, besserer Code! 👍

@davidjoy woah, danke fürs Teilen! Ich mache das Gleiche, muss es auch versuchen!

@davidjoy Habe gerade auch meine

Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivitäten gab. Es wird geschlossen, wenn keine weitere Aktivität stattfindet. Vielen Dank für Ihre Beiträge.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen