<p>react-dnd puede llamar a un componente desmontado causando un error no detectado: no se pudo encontrar un targetId válido</p>

Creado en 2 jun. 2019  ·  3Comentarios  ·  Fuente: react-dnd/react-dnd

Describe el error
es posible que react-dnd llame a una función de recopilación que haga que un componente se desmonte, luego realice otra llamada de recopilación () en el componente desmontado, provocando un error no detectado "No se pudo encontrar un targetId válido".

Redux en su despacho () de los eventos Backend Drag And Drop hace una copia de todos los oyentes de los eventos suscritos al principio y siempre los llama independientemente de las suscripciones redux que se hayan cancelado mientras se notifica a los suscriptores (consulte https://stackoverflow.com/questions / 43356080 / redux-unsubscribe-within-componentwillunmount-still-calls-subscribe-callback). Esto significa que si algo como un evento de arrastre html5 'EndDrag' activa una notificación en handleChange () en react-dnd / src / decorateHandler.tsx: handleChange (), y la primera llamada a collect () provoca un desmontaje de un componente, el El componente desmontado subsiguiente puede tener su llamada Collect () activada en una notificación posterior del mismo evento.

Por lo tanto, el invariante 'Se espera encontrar un objetivo válido' se activa porque el componente se ha eliminado válidamente del registro de Id de objetivos válidos, pero la notificación llama a un componente desmontado.

Descubrí este problema al intentar integrar react-sortable-tree, que usa react-dnd en mi aplicación. Puede ver un ejemplo del problema y un caso de prueba recreable aquí: https://github.com/frontend-collective/react-sortable-tree/issues/490. Un arrastrar y soltar que se cancela liberando un dragSource fuera del dragTarget reproduce este problema cada vez.

El error no detectado y el seguimiento de la pila se pegan a continuación. El seguimiento de la pila muestra que la función de conexión está llamando a monitor.canDrop () que falla en los componentes desmontados.
browser.js: 38 Violación invariante no detectada: se esperaba encontrar un objetivo válido.en invariante (https://xzoq6xprlz.codesandbox.io/node_modules/invariant/browser.js:38:15)en DragDropMonitorImpl.canDropOnTarget (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:67:9)
en DropTargetMonitorImpl.canDrop (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/DropTargetMonitorImpl.js:24:41)
en nodeDropTargetPropInjection (https://xzoq6xprlz.codesandbox.io/node_modules/react-sortable-tree/dist/index.cjs.js:2367:28)
en DragDropContainer.getCurrentState (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:116:29)
en DragDropContainer._this.handleChange (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:45:39)
en handleChange (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:27:21)
al despacho (https://xzoq6xprlz.codesandbox.io/node_modules/redux/lib/redux.js:220:7)
en Object.eval [como endDrag] (https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropManagerImpl.js:67:21)
en HTML5Backend.handleTopDragEndCapture (https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd-html5-backend/lib/cjs/HTML5Backend.js:145:31)
''

Solución alterna

Llamar a componentes desmontados probablemente no sea el comportamiento correcto, por lo que agregué una declaración if en react-dnd / src / decorateHandler.tsx: handleChange que elimina la notificación si decorateHandler ya ha sido cancelado. diff adjunto.

diff --git a/packages/react-dnd/src/decorateHandler.tsx b/packages/react-dnd/src/decorateHandler.tsx
index 85385ec..bcd149e 100644
--- a/packages/react-dnd/src/decorateHandler.tsx
+++ b/packages/react-dnd/src/decorateHandler.tsx
@@ -159,6 +159,15 @@ export default function decorateHandler<Props, CollectedProps, ItemIdType>({
                }

                public handleChange = () => {
+                       if (this.disposable.isDisposed) {
+                               console.log("in handleChange")
+                               //because redux takes a snapshot of all subscribers to 
+                               //events when it starts dispatch, it is still possible to call into this even after 
+                               //the subscription has been unsubscribed
+                               //to prevent against calling into unmounted objects, return immediately
+
+                               return
+                       }
                        const nextState = this.getCurrentState()
                        if (!shallowEqual(nextState, this.state)) {
                                this.setState(nextState)
wontfix

Comentario más útil

@ mx2323 ¿ esto fue introducido? Incluso si se trataba de react-sortable-tree todavía necesita las últimas actualizaciones de react-dnd, creo que está esperando

Todos 3 comentarios

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.

@ mx2323 ¿ esto fue introducido? Incluso si se trataba de react-sortable-tree todavía necesita las últimas actualizaciones de react-dnd, creo que está esperando

No terminé empujándolo.

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