diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js index 97bfa60274dd0..14e80522b196c 100644 --- a/packages/react-dom/src/client/ReactDOMHostConfig.js +++ b/packages/react-dom/src/client/ReactDOMHostConfig.js @@ -190,6 +190,11 @@ export function getChildHostContextForEvent( let eventData = null; if (type === REACT_EVENT_COMPONENT_TYPE) { + warning( + parentHostContextDev.eventData === null || + !parentHostContextDev.eventData.isEventTarget, + 'validateDOMNesting: React event targets must not have event components as children.', + ); eventData = { isEventComponent: true, isEventTarget: false, diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index 1d7fa86fbc91e..585406898e2e1 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -268,6 +268,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { ) { if (__DEV__ && enableEventAPI) { if (type === REACT_EVENT_COMPONENT_TYPE) { + warning( + parentHostContext !== EVENT_TARGET_CONTEXT, + 'validateDOMNesting: React event targets must not have event components as children.', + ); return EVENT_COMPONENT_CONTEXT; } else if (type === REACT_EVENT_TARGET_TYPE) { warning( diff --git a/packages/react-reconciler/src/__tests__/ReactFiberEvents-test-internal.js b/packages/react-reconciler/src/__tests__/ReactFiberEvents-test-internal.js index 40911388c71c6..3cfed203ad4c7 100644 --- a/packages/react-reconciler/src/__tests__/ReactFiberEvents-test-internal.js +++ b/packages/react-reconciler/src/__tests__/ReactFiberEvents-test-internal.js @@ -200,6 +200,25 @@ describe('ReactFiberEvents', () => { 'Warning: validateDOMNesting: React event targets must be direct children of event components.', ); }); + + it('should warn if an event target has an event component as a child', () => { + const Test = () => ( + + + + Child 1 + + + + ); + + expect(() => { + ReactNoop.render(); + expect(Scheduler).toFlushWithoutYielding(); + }).toWarnDev( + 'Warning: validateDOMNesting: React event targets must not have event components as children.', + ); + }); }); describe('TestRenderer', () => { @@ -368,6 +387,26 @@ describe('ReactFiberEvents', () => { 'Warning: validateDOMNesting: React event targets must be direct children of event components.', ); }); + + it('should warn if an event target has an event component as a child', () => { + const Test = () => ( + + + + Child 1 + + + + ); + + const root = ReactTestRenderer.create(null); + expect(() => { + root.update(); + expect(Scheduler).toFlushWithoutYielding(); + }).toWarnDev( + 'Warning: validateDOMNesting: React event targets must not have event components as children.', + ); + }); }); describe('ReactDOM', () => { @@ -535,6 +574,26 @@ describe('ReactFiberEvents', () => { 'Warning: validateDOMNesting: React event targets must be direct children of event components.', ); }); + + it('should warn if an event target has an event component as a child', () => { + const Test = () => ( + + + + Child 1 + + + + ); + + expect(() => { + const container = document.createElement('div'); + ReactDOM.render(, container); + expect(Scheduler).toFlushWithoutYielding(); + }).toWarnDev( + 'Warning: validateDOMNesting: React event targets must not have event components as children.', + ); + }); }); describe('ReactDOMServer', () => { diff --git a/packages/react-test-renderer/src/ReactTestHostConfig.js b/packages/react-test-renderer/src/ReactTestHostConfig.js index a86fc4b266517..a5ac30273baae 100644 --- a/packages/react-test-renderer/src/ReactTestHostConfig.js +++ b/packages/react-test-renderer/src/ReactTestHostConfig.js @@ -133,6 +133,10 @@ export function getChildHostContextForEvent( ): HostContext { if (__DEV__ && enableEventAPI) { if (type === REACT_EVENT_COMPONENT_TYPE) { + warning( + parentHostContext !== EVENT_TARGET_CONTEXT, + 'validateDOMNesting: React event targets must not have event components as children.', + ); return EVENT_COMPONENT_CONTEXT; } else if (type === REACT_EVENT_TARGET_TYPE) { warning(