<p>react-dndはマウントされていないコンポーネントを呼び出すことができ、 `Uncaught Error:Could not find a validtargetId`を引き起こします</p>

作成日 2019年06月02日  ·  3コメント  ·  ソース: react-dnd/react-dnd

バグを説明する
react-dndが、コンポーネントをアンマウントするコレクトコールを呼び出してから、アンマウントされたコンポーネントに対して別のcollect()呼び出しを行うと、「有効なtargetIdが見つかりませんでした」というキャッチされないエラーが発生する可能性があります。

バックエンドのドラッグアンドドロップイベントのdispatch()でのReduxは、最初にサブスクライブされたイベントのすべてのリスナーのコピーを作成し、サブスクライバーに通知している間、サブスクライブ解除されたreduxサブスクリプションに関係なく常にそれらを呼び出します(https://stackoverflow.com/questionsを参照) / 43356080 / redux-unsubscribe-within-componentwillunmount-still-calls-subscribe-callback)。 これは、「EndDrag」html5ドラッグイベントのようなものがreact-dnd / src / decodeHandler.tsx:handleChange()のhandleChange()で通知をトリガーし、最初のcollect()呼び出しがコンポーネントのアンマウントを引き起こす場合、後続のマウントされていないコンポーネントでは、同じイベントの後続の通知でcollect()呼び出しがトリガーされる場合があります。

したがって、コンポーネントが有効なターゲットIDのレジストリから有効に削除されたため、不変条件「有効なターゲットの検出が期待されます」がトリガーされますが、通知はマウントされていないコンポーネントを呼び出しています。

この問題は、react-dndを使用するreact-sortable-treeをアプリに統合しようとしたときに発見しました。 問題の例と再現可能なテストケースは、https://github.com/frontend-collective/react-sortable-tree/issues/490で確認できます。 dragTargetの外部でdragSourceを解放することによってキャンセルされるドラッグアンドドロップは、毎回この問題を再現します。

キャッチされなかったエラーとスタックトレースは以下に貼り付けられています。スタックトレースは、接続関数がmonitor.canDrop()を呼び出していることを示していますが、マウントされていないコンポーネントでは失敗します。
browser.js:38 Uncaught Invariant Violation:有効なターゲットを見つけることが期待されます。不変で(https://xzoq6xprlz.codesandbox.io/node_modules/invariant/browser.js:38:15)DragDropMonitorImpl.canDropOnTarget(https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:67:9)で
DropTargetMonitorImpl.canDrop(https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/DropTargetMonitorImpl.js:24:41)
nodeDropTargetPropInjection(https://xzoq6xprlz.codesandbox.io/node_modules/react-sortable-tree/dist/index.cjs.js:2367:28)
DragDropContainer.getCurrentState(https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:116:29)で
DragDropContainer._this.handleChange(https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd/lib/cjs/decorateHandler.js:45:39)で
handleChangeで(https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropMonitorImpl.js:27:21)
ディスパッチ時(https://xzoq6xprlz.codesandbox.io/node_modules/redux/lib/redux.js:220:7)
Object.evalで[endDragとして](https://xzoq6xprlz.codesandbox.io/node_modules/dnd-core/lib/cjs/DragDropManagerImpl.js:67:21)
HTML5Backend.handleTopDragEndCapture(https://xzoq6xprlz.codesandbox.io/node_modules/react-dnd-html5-backend/lib/cjs/HTML5Backend.js:145:31)

回避策

マウントされていないコンポーネントの呼び出しはおそらく正しい動作ではないため、react-dnd / src /decorateHandler.tsx:handleChangeにifステートメントを追加しました。これは、decorateHandlerが既にサブスクライブされていない場合に通知をドロップします。 デフ付き。

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

最も参考になるコメント

@ mx2323これは押し込まれましたか? それがreact-sortable-treeであったとしても、最新のreact-dndアップデートが必要ですが、待っていると思います

全てのコメント3件

この問題は、最近のアクティビティがないため、自動的に古いものとしてマークされています。 それ以上のアクティビティが発生しない場合は閉じられます。 貢献していただきありがとうございます。

@ mx2323これは押し込まれましたか? それがreact-sortable-treeであったとしても、最新のreact-dndアップデートが必要ですが、待っていると思います

私はそれを押すことになったわけではありません。

このページは役に立ちましたか?
0 / 5 - 0 評価