From 7fb94a57d05f4e9af85f9db726500f300073870d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20S=C3=B8rensen?= Date: Fri, 22 Mar 2019 16:33:35 +0100 Subject: [PATCH] fix: throw error when a DragSource or DropTarget is rendered outside DragDropContext (#1132) (#1286) Previously the HOC's would just return null, leading to "missing" components, with nothing pointing in the direction of the problem being a missing DrapDropContext. --- .../react-dnd/src/__tests__/DragSource.spec.tsx | 14 ++++++++++++++ .../react-dnd/src/__tests__/DropTarget.spec.tsx | 16 ++++++++++++++++ packages/react-dnd/src/decorateHandler.tsx | 14 ++++++++------ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/packages/react-dnd/src/__tests__/DragSource.spec.tsx b/packages/react-dnd/src/__tests__/DragSource.spec.tsx index 753a7bfb1d..5c53eab644 100644 --- a/packages/react-dnd/src/__tests__/DragSource.spec.tsx +++ b/packages/react-dnd/src/__tests__/DragSource.spec.tsx @@ -1,5 +1,6 @@ // tslint:disable max-classes-per-file import * as React from 'react' +import * as TestUtils from 'react-dom/test-utils' import { DragSource } from '../index' describe('DragSource', () => { @@ -42,4 +43,17 @@ describe('DragSource', () => { expect(DecoratedComponent).toBeDefined() }) + + it('throws an error if rendered outside a DragDropContext', () => { + const Component: React.FC<{}> = () => null + const DecoratedComponent = DragSource( + 'abc', + { beginDrag: () => null }, + () => ({}), + )(Component) + + expect(() => { + TestUtils.renderIntoDocument() + }).toThrow(/Could not find the drag and drop manager in the context/) + }) }) diff --git a/packages/react-dnd/src/__tests__/DropTarget.spec.tsx b/packages/react-dnd/src/__tests__/DropTarget.spec.tsx index 222d8e9ed9..4ad3acab92 100644 --- a/packages/react-dnd/src/__tests__/DropTarget.spec.tsx +++ b/packages/react-dnd/src/__tests__/DropTarget.spec.tsx @@ -1,5 +1,6 @@ // tslint:disable max-classes-per-file import * as React from 'react' +import * as TestUtils from 'react-dom/test-utils' import { DropTarget } from '../index' describe('DropTarget', () => { @@ -27,4 +28,19 @@ describe('DropTarget', () => { expect(DecoratedComponent).toBeDefined() }) + + it('throws an error if rendered outside a DragDropContext', () => { + const Component: React.FC<{}> = () => null + const DecoratedComponent = DropTarget( + 'abc', + { + drop: () => ({}), + }, + () => ({}), + )(Component) + + expect(() => { + TestUtils.renderIntoDocument() + }).toThrow(/Could not find the drag and drop manager in the context/) + }) }) diff --git a/packages/react-dnd/src/decorateHandler.tsx b/packages/react-dnd/src/decorateHandler.tsx index 21f341ca1c..3d13120136 100644 --- a/packages/react-dnd/src/decorateHandler.tsx +++ b/packages/react-dnd/src/decorateHandler.tsx @@ -199,9 +199,6 @@ export default function decorateHandler({ return ( {({ dragDropManager }) => { - if (dragDropManager === undefined) { - return null - } this.receiveDragDropManager(dragDropManager) requestAnimationFrame(() => this.handlerConnector!.reconnect()) return ( @@ -217,19 +214,24 @@ export default function decorateHandler({ ) } - private receiveDragDropManager(dragDropManager: DragDropManager) { + private receiveDragDropManager(dragDropManager?: DragDropManager) { if (this.manager !== undefined) { return } - this.manager = dragDropManager + invariant( - typeof dragDropManager === 'object', + dragDropManager !== undefined, 'Could not find the drag and drop manager in the context of %s. ' + 'Make sure to wrap the top-level component of your app with DragDropContext. ' + 'Read more: http://react-dnd.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context', displayName, displayName, ) + if (dragDropManager === undefined) { + return + } + + this.manager = dragDropManager this.handlerMonitor = createMonitor(dragDropManager) this.handlerConnector = createConnector(dragDropManager.getBackend()) this.handler = createHandler(this.handlerMonitor, this.decoratedRef)