React-dnd: Avertissement avec DragSource imbriqué

Créé le 6 avr. 2016  ·  27Commentaires  ·  Source: react-dnd/react-dnd

Si vous avez une DragSource à l'intérieur d'un composant qui est également une DragSource (c'est-à-dire faites glisser quelque chose dans un glisser-déposer), chaque fois que le composant parent est déplacé, l'avertissement suivant apparaît.

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

Un exemple de ceci serait:

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>
        );
    }
}

Je crois que le problème vient du fait que le rendu du composant parent provoque l'appel de l'enfant DragSource à passer un appel à setState pendant l'appel de la fonction receiveProps?

triage wontfix

Commentaire le plus utile

Juste au cas où cela aiderait quelqu'un: j'ai rencontré cela lorsque je rendais un composant qui était une source de glissement dans mon calque de glissement personnalisé, car c'était pratique. J'ai utilisé le composant source de glisser parce que c'était la même entité que j'essayais de faire glisser, donc il était logique pour moi de garder le code "DRY" en le réutilisant. Je n'ai pas pensé au fait qu'il contenait tout le code dragSource - en regardant en arrière, _ bien sûr_ je ne voudrais pas qu'une source de glissement COMME la chose à rendre dans le calque de glissement personnalisé.

J'ai finalement divisé mon composant en une version "Glissable" qui enveloppait le composant de base, puis j'ai utilisé le composant de base dans mon calque de glissement personnalisé. Plus d'avertissement, meilleur code! 👍

Tous les 27 commentaires

: +1:

Pouvez-vous nous fournir un projet reproduisant le problème?

J'essaie de produire un exemple simple et j'ai des problèmes de reproduction en dehors de mon projet privé sur lequel je travaille. @nihtalak , avez-vous un repo sur Github qui génère le problème?

Voici un petit dépôt présentant le comportement décrit: https://github.com/ebakan/react-dnd-nested-bug

Curieusement, le Component ne lève cette erreur que lorsqu'il écoute monitor.getItem() . S'il écoute monitor.isDragging() il fonctionnera correctement, comme indiqué dans cette branche: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is- traînant

Il lancera également l'erreur lors de l'écoute de monitor.getItemType() : https://github.com/ebakan/react-dnd-nested-bug/tree/error-with-get-item-type

@ebakan - intéressant. Je me demande ce qui cause ce bogue dans mon code, qui utilise isDragging. Je fais des choses bizarres avec le draggable imbriqué, donc cela pourrait être une manifestation du même bug que vous voyez. Merci pour l'aide à la reproduction!

J'ai également imbriqué des draggables, mais je ne sais pas si c'est le problème.
Il semble créer un nouveau magasin et le code qui écoute. J'ai fait une vidéo si cela aide:
http://screencast.com/t/qCrJRPAS2MYR

Mise à jour: j'ai trouvé le problème, il me restait un auditeur donc dans mon cas, ce n'était pas dû à react-dnd.
Update2: J'ai parlé trop tôt. En supprimant l'auditeur restant, je reçois toujours l'avertissement.

Je viens d'ajouter Dnd à un autre composant et j'ai remarqué ce problème même sans composants imbriqués ou à glissement multiple.

Après quelques recherches, j'ai trouvé que le problème était lié au calque de glissement personnalisé rendant le composant tout en étant glissé.

Si je mets du texte à la place du composant glissé, cela fonctionne très bien. Le composant lui-même est la source de glissement.

@jchristman @hakunin Je n'ai pas de Cannot update during an existing state transition quand j'avais une cible de dépôt rendue conditionnellement basée sur isDragging . Cela pourrait-il être le cas dans l'un de vos exemples? Quelque chose comme ça:

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

J'ai fini par contourner le problème en utilisant display: none/block pour masquer la cible au lieu d'ajouter et de supprimer le composant lorsque le glissement est actif.

Je pense que cela pourrait être le problème. Je vais vérifier et vous informer. C'est certainement la construction que j'utilise actuellement.

Naw - J'obtiens le problème lorsque la "baisse" se produit. Ensuite, il tente de rendre le composant et lance cet avertissement.

J'ai le même avertissement lorsque mon aperçu de glisser était un composant qui était une DragSource (ce que je ne suis pas censé faire).

@jchristman avez-vous déjà trouvé une solution pour cela?

Je travaille avec des dragSources imbriquées et j'ai soudainement commencé à voir cette erreur lors de la suppression de la ressource imbriquée.

Je peux donner un exemple, mais je voulais voir si quelqu'un avait résolu le problème ou avait une solution de contournement appropriée.

J'ai le même avertissement lorsque mon aperçu de glisser était un composant qui était une DragSource (ce que je ne suis pas censé faire).

Merci @arjunu, mon avertissement a été causé par cela!
Je les ai encore de temps en temps, donc je suppose que d'autres raisons doivent également être corrigées. Peut-être de ma part :)

@ gharwood1 , je vis juste le problème jusqu'à ce qu'il puisse être corrigé. J'ai passé quelques heures une fois à essayer de vraiment comprendre cette bibliothèque afin de pouvoir extraire une demande de correctif, mais c'est assez complexe, alors j'ai continué. Je n'ai juste pas le temps ... :-(

@gaearon Je n'ai pas vraiment de projet capable de faire tomber quelqu'un, mais je pense que je peux en faire un si nécessaire.

Fondamentalement, ce que j'essaie de faire ici est valable:

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

Si je désactive le conditionnel à la ligne 64, tout va bien

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

mais dès que les résultats de l'événement de glissement commencent à modifier les accessoires et le rendu des composants, l'avertissement ci-dessus commence à se répandre fréquemment.

Ne devrais-je pas faire ça?

Le cas d'utilisation consiste essentiellement à "prévisualiser" l'élément actuellement glissé dans la cible de dépôt. Ce qui précède est une preuve de concept - pas encore connecté au magasin Redux, car je ne suis pas sûr que cela soit même valide.


Hm, on dirait que ça va si je garde mes modifications locales à SubjectDisplayContent , mais les avertissements commencent à se produire si les changements s'étendent à SubjectDisplay . Donc, fondamentalement, si un dropTarget envoie des accessoires qui modifient un dropTarget différent, react-dnd s'énerve. Est-ce prévu, et j'ai besoin de repenser certaines choses, ou est-ce un bug avec dnd?

Je rencontre exactement le même problème. Ce que vous pouvez faire dans certaines situations est de créer un DragDropContext autour de chaque déplaçable imbriqué. Mais cela ne fonctionne pas dès que vous voulez un DragLayer personnalisé.

J'ai eu la même erreur, sauf que je fais un dropTargets imbriqué.
Après avoir regardé dans la documentation, j'ai essayé d'utiliser

isOver (options): renvoie true si une opération de glissement est en cours et que le pointeur survole actuellement le propriétaire. Vous pouvez éventuellement passer {shallow: true} pour vérifier strictement si seul le propriétaire est survolé, par opposition à une cible imbriquée.

(avec l'option shallow is true) dans la fonction canDrop du parent dropTarget, et le problème a disparu. Je pense que la même chose pourrait s'appliquer à d'autres scénarios.

@jchenjc J'ai essayé cela mais cela n'a pas fonctionné pour moi. Pour être honnête, ma situation est extrêmement compliquée avec un aperçu du glissement imbriqué + une source de glissement + une cible de dépôt qui doit fonctionner sur les listes.

FWIW: J'ai à la fois des sources de glissement imbriquées et un calque de glissement personnalisé. Lorsque je supprime le calque de glissement personnalisé, le message disparaît. Après avoir inspecté la trace de la pile, il semble que le problème soit ici:

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

Le code pertinent est ici . Je vais examiner pourquoi l'état pourrait être différent dans mon cas pour déclencher un nouveau rendu ...

Avec un dragsource + droptarget imbriqué dans un droptarget, j'obtiens ce problème.

Cela est en partie dû au fait que gaearon a envisagé de faire un glisser-déposer de liste en faisant de chaque élément de la liste une cible de dépôt, plutôt que de faire du composant de liste une seule cible de dépôt qui détermine ce qu'il faut faire en fonction de la position du survol du glisser-déposer. La dernière façon est la façon dont la plupart des autres systèmes DnD que j'ai vus font les choses.

Juste au cas où cela aiderait quelqu'un: j'ai rencontré cela lorsque je rendais un composant qui était une source de glissement dans mon calque de glissement personnalisé, car c'était pratique. J'ai utilisé le composant source de glisser parce que c'était la même entité que j'essayais de faire glisser, donc il était logique pour moi de garder le code "DRY" en le réutilisant. Je n'ai pas pensé au fait qu'il contenait tout le code dragSource - en regardant en arrière, _ bien sûr_ je ne voudrais pas qu'une source de glissement COMME la chose à rendre dans le calque de glissement personnalisé.

J'ai finalement divisé mon composant en une version "Glissable" qui enveloppait le composant de base, puis j'ai utilisé le composant de base dans mon calque de glissement personnalisé. Plus d'avertissement, meilleur code! 👍

@davidjoy woah, merci pour le partage! Je fais la même chose, je dois l'essayer aussi!

@davidjoy Je

Ce problème a été automatiquement marqué comme obsolète car il n'a pas eu d'activité récente. Il sera fermé si aucune autre activité n'a lieu. Merci pour vos contributions.

Cette page vous a été utile?
0 / 5 - 0 notes