diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js
index d3e49e974f37..a2f2a26e7ff3 100644
--- a/packages/react-dom/src/client/ReactDOMHostConfig.js
+++ b/packages/react-dom/src/client/ReactDOMHostConfig.js
@@ -1172,8 +1172,8 @@ export function validateEventListenerTarget(
console.warn(
'Event listener method setListener() from useEvent() hook requires the first argument to be either:' +
'\n\n' +
- '1. A valid DOM node that was rendered and managed by React' +
- '2. The "window" object' +
+ '1. A valid DOM node that was rendered and managed by React\n' +
+ '2. The "window" object\n' +
'3. The "document" object',
);
}
diff --git a/packages/react-dom/src/client/ReactDOMUseEvent.js b/packages/react-dom/src/client/ReactDOMUseEvent.js
index 6eb2c1dff293..5c00306c58e0 100644
--- a/packages/react-dom/src/client/ReactDOMUseEvent.js
+++ b/packages/react-dom/src/client/ReactDOMUseEvent.js
@@ -46,7 +46,7 @@ export function useEvent(
): ReactDOMListenerMap {
const dispatcher = resolveDispatcher();
let capture = false;
- let passive = false;
+ let passive = undefined; // Undefined means to use the browser default
let priority = getEventPriorityForListenerSystem((type: any));
if (options != null) {
diff --git a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
index 3df6dbbc926e..7dc14441a7e6 100644
--- a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
+++ b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
@@ -1318,6 +1318,55 @@ describe('DOMModernPluginEventSystem', () => {
expect(log[5]).toEqual(['bubble', buttonElement]);
});
+ it('handle propagation of click events mixed with onClick events', () => {
+ const buttonRef = React.createRef();
+ const divRef = React.createRef();
+ const log = [];
+ const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));
+ const onClickCapture = jest.fn(e =>
+ log.push(['capture', e.currentTarget]),
+ );
+
+ function Test() {
+ const click = ReactDOM.unstable_useEvent('click');
+ const clickCapture = ReactDOM.unstable_useEvent('click', {
+ capture: true,
+ });
+
+ React.useEffect(() => {
+ click.setListener(buttonRef.current, onClick);
+ clickCapture.setListener(buttonRef.current, onClickCapture);
+ });
+
+ return (
+
+ );
+ }
+
+ ReactDOM.render(, container);
+ Scheduler.unstable_flushAll();
+
+ let buttonElement = buttonRef.current;
+ dispatchClickEvent(buttonElement);
+ expect(onClick).toHaveBeenCalledTimes(1);
+ expect(onClickCapture).toHaveBeenCalledTimes(1);
+ expect(log[0]).toEqual(['capture', buttonElement]);
+ expect(log[1]).toEqual(['bubble', buttonElement]);
+
+ let divElement = divRef.current;
+ dispatchClickEvent(divElement);
+ expect(onClick).toHaveBeenCalledTimes(3);
+ expect(onClickCapture).toHaveBeenCalledTimes(3);
+ expect(log[2]).toEqual(['capture', buttonElement]);
+ expect(log[3]).toEqual(['capture', divElement]);
+ expect(log[4]).toEqual(['bubble', divElement]);
+ expect(log[5]).toEqual(['bubble', buttonElement]);
+ });
+
it('should correctly work for a basic "click" listener on the outer target', () => {
const log = [];
const clickEvent = jest.fn(event => {
diff --git a/packages/shared/ReactDOMTypes.js b/packages/shared/ReactDOMTypes.js
index fbad9e5e5d3e..9c76e7675ab2 100644
--- a/packages/shared/ReactDOMTypes.js
+++ b/packages/shared/ReactDOMTypes.js
@@ -78,7 +78,7 @@ export type ReactDOMResponderContext = {
export type ReactDOMListenerEvent = {|
capture: boolean,
- passive: boolean,
+ passive: void | boolean,
priority: EventPriority,
type: string,
|};