React-dnd: Advertencia con DragSource anidado

Creado en 6 abr. 2016  ·  27Comentarios  ·  Fuente: react-dnd/react-dnd

Si tiene un DragSource dentro de un componente que también es un DragSource (es decir, arrastre algo dentro de un elemento que se puede arrastrar), siempre que se arrastre el componente principal, aparecerá la siguiente advertencia.

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 ejemplo de esto sería:

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

Creo que el problema se debe al hecho de que volver a renderizar el componente principal hace que la llamada secundaria DragSource haga una llamada a setState durante la llamada a la función ReceiveProps.

triage wontfix

Comentario más útil

Por si acaso ayuda a alguien: me encontré con esto cuando estaba renderizando un componente que era una fuente de arrastre en mi capa de arrastre personalizada porque era conveniente. Utilicé el componente de origen de arrastre porque era la misma entidad que estaba tratando de arrastrar, por lo que tenía sentido para mí mantener el código en "SECO" reutilizándolo. No pensé en el hecho de que tenía todo el código dragSource en él; mirando hacia atrás, _por supuesto_, no querría una fuente de arrastre COMO la cosa para renderizar en la capa de arrastre personalizada.

Finalmente dividí mi componente en una versión "arrastrable" que envolvía el componente base, y luego usé el componente base en mi capa de arrastre personalizada. ¡No más advertencias, mejor código! 👍

Todos 27 comentarios

: +1:

¿Puede proporcionar un proyecto que reproduzca el problema?

Estoy tratando de producir un ejemplo simple y tengo problemas para reproducir fuera de mi proyecto privado en el que estoy trabajando. @nihtalak , ¿tienes un repositorio en Github que produce el problema?

Aquí hay un pequeño repositorio que muestra el comportamiento descrito: https://github.com/ebakan/react-dnd-nested-bug

Curiosamente, Component solo arroja este error cuando está escuchando monitor.getItem() . Si está escuchando monitor.isDragging() , funcionará correctamente, como se muestra en esta rama: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is- arrastrando

También arrojará el error al escuchar monitor.getItemType() : https://github.com/ebakan/react-dnd-nested-bug/tree/error-with-get-item-type

@ebakan - interesante. Me pregunto qué está causando que aparezca este error en mi código, que usa isDragging. Estoy haciendo algunas cosas raras con el arrastrable anidado, por lo que podría ser una manifestación del mismo error que está viendo. ¡Gracias por la ayuda con la reproducción!

También he anidado draggables, pero no estoy seguro de si ese es el problema.
Parece estar creando una nueva tienda y el código que está escuchando. Hice un video si eso ayuda:
http://screencast.com/t/qCrJRPAS2MYR

Actualización: encontré el problema, tenía un oyente sobrante, así que en mi caso no se debió a react-dnd.
Update2: hablé demasiado pronto. Al eliminar el oyente sobrante, todavía recibo la advertencia.

Acabo de agregar Dnd a otro componente y noté este problema incluso sin componentes de arrastre anidados o múltiples.

Después de investigar un poco, descubrí que el problema está relacionado con la capa de arrastre personalizada que representa el componente mientras se arrastra.

Si pongo texto en su lugar, el componente que se está arrastrando funciona bien. El componente en sí es la fuente de arrastre.

@jchristman @hakunin No tengo draggables anidados, pero Cannot update during an existing state transition cuando tenía un destino de colocación condicionalmente renderizado basado en isDragging . ¿Podría ser este el caso en alguno de sus ejemplos? Algo parecido a esto:

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

Terminé trabajando alrededor de él usando display: none/block para ocultar el objetivo en lugar de agregar y eliminar el componente cuando el arrastre está activo.

Creo que ese podría ser el problema. Voy a revisar y te aviso. Esa es definitivamente la construcción que estoy usando ahora.

No, me aparece el problema cuando ocurre la "caída". Luego intenta volver a entregar el componente y lanza esta advertencia.

Recibí la misma advertencia cuando mi vista previa de arrastre era un componente que era un DragSource (que se supone que no debo hacer).

@jchristman , ¿alguna vez se te ocurrió una solución para esto?

Estoy trabajando con dragSources anidados y de repente comencé a ver este error al soltar el recurso anidado.

Puedo proporcionar un ejemplo, pero quería ver si alguien había resuelto el problema o tenía una solución alternativa adecuada.

Recibí la misma advertencia cuando mi vista previa de arrastre era un componente que era un DragSource (que se supone que no debo hacer).

Gracias @arjunu, mi advertencia fue causada por esto!
Todavía tengo estos de vez en cuando, así que supongo que también hay otra razón para solucionarlos. Podría estar de mi parte :)

@ gharwood1 , solo estoy viviendo con el problema hasta que se pueda solucionar. Una vez pasé algunas horas tratando de comprender realmente esta biblioteca para poder solicitar una solución, pero es bastante complejo, así que seguí adelante. Simplemente no tengo tiempo ... :-(

@gaearon No tengo un proyecto hecho que sea capaz de que alguien lo derribe, pero creo que puedo hacer uno si es necesario.

Básicamente, lo que estoy tratando de hacer aquí es válido:

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

Si desactivo el condicional en la línea 64, todo está bien

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

pero en el momento en que los resultados del evento de arrastre comienzan a modificar los accesorios y la representación de los componentes, la advertencia anterior comienza a aparecer con frecuencia.

¿No debería estar haciendo esto?

El caso de uso consiste básicamente en "previsualizar" el elemento actualmente arrastrado en el destino de colocación. Lo anterior es una prueba de concepto: aún no está conectado a la tienda Redux, ya que no estoy seguro de si esto es válido.


Hm, parece que está bien si mantengo mis cambios locales en SubjectDisplayContent , pero las advertencias comienzan a aparecer si los cambios se extienden a SubjectDisplay . Entonces, básicamente, si un dropTarget envía accesorios que modifican un dropTarget diferente , react-dnd se molesta. ¿Es esto esperado y necesito repensar algunas cosas, o es un error con dnd?

Estoy experimentando exactamente el mismo problema. Lo que puede hacer en algunas situaciones es crear un DragDropContext alrededor de cada elemento arrastrable anidado. Pero esto no funciona tan pronto como desea un DragLayer personalizado ...

Recibí el mismo error, excepto que estoy haciendo un dropTargets anidado.
Después de buscar en la documentación, intenté usar

isOver (opciones): Devuelve verdadero si hay una operación de arrastre en curso y el puntero se encuentra actualmente sobre el propietario. Opcionalmente, puede pasar {shallow: true} para verificar estrictamente si solo se está desplazando al propietario, a diferencia de un objetivo anidado.

(con la opción superficial es verdadera) en la función canDrop del principal dropTarget, y el problema desapareció. Creo que lo mismo podría aplicarse a otros escenarios.

@jchenjc Intenté esto pero no funcionó para mí. Para ser honesto, mi situación es extremadamente complicada con la vista previa de arrastre anidada + la fuente de arrastre + el destino de colocación que debe funcionar en todas las listas.

FWIW: Tengo fuentes de arrastre anidadas y una capa de arrastre personalizada. Cuando elimino la capa de arrastre personalizada, el mensaje desaparece. Al inspeccionar el seguimiento de la pila, parece que el problema está aquí:

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

El código relevante está aquí . Voy a investigar por qué el estado podría ser diferente en mi caso para desencadenar una repetición ...

Con un dragsource + droptarget anidado dentro de un droptarget, obtengo este problema.

Parte de la razón por la que esto sucedió es porque gaearon imaginó hacer la lista de arrastrar y soltar haciendo que cada elemento de la lista sea un destino de colocación, en lugar de convertir el componente de la lista en un único destino de colocación que determina qué hacer en función de la posición de desplazamiento del arrastre. La última forma es la forma en que la mayoría de los otros sistemas DnD que he visto hacen las cosas.

Por si acaso ayuda a alguien: me encontré con esto cuando estaba renderizando un componente que era una fuente de arrastre en mi capa de arrastre personalizada porque era conveniente. Utilicé el componente de origen de arrastre porque era la misma entidad que estaba tratando de arrastrar, por lo que tenía sentido para mí mantener el código en "SECO" reutilizándolo. No pensé en el hecho de que tenía todo el código dragSource en él; mirando hacia atrás, _por supuesto_, no querría una fuente de arrastre COMO la cosa para renderizar en la capa de arrastre personalizada.

Finalmente dividí mi componente en una versión "arrastrable" que envolvía el componente base, y luego usé el componente base en mi capa de arrastre personalizada. ¡No más advertencias, mejor código! 👍

@davidjoy woah, ¡gracias por compartir! Estoy haciendo lo mismo, ¡necesito probarlo también!

@davidjoy Acabo de arreglar el mío también. Su sugerencia apunta a no usar DragSource y demás para la capa personalizada. Lo que hice fue simplemente usar el componente desnudo sin DragSource en mi capa de arrastre personalizada y eso funcionó.

Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias por sus aportaciones.

¿Fue útil esta página
0 / 5 - 0 calificaciones