diff --git a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
index 1e6169cb5588c..a6918c69197e1 100644
--- a/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
@@ -12,11 +12,13 @@
describe('ReactDOMEventListener', () => {
let React;
let ReactDOM;
+ let ReactDOMServer;
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactDOM = require('react-dom');
+ ReactDOMServer = require('react-dom/server');
});
describe('Propagation', () => {
@@ -797,4 +799,108 @@ describe('ReactDOMEventListener', () => {
document.body.removeChild(container);
}
});
+
+ it('should subscribe to scroll during updates', () => {
+ const container = document.createElement('div');
+ const ref = React.createRef();
+ const log = [];
+ const onScroll = jest.fn(e =>
+ log.push(['bubble', e.currentTarget.className]),
+ );
+ const onScrollCapture = jest.fn(e =>
+ log.push(['capture', e.currentTarget.className]),
+ );
+ document.body.appendChild(container);
+ try {
+ ReactDOM.render(
+
,
+ container,
+ );
+ ReactDOM.render(
+ ,
+ container,
+ );
+ ref.current.dispatchEvent(
+ new Event('scroll', {
+ bubbles: false,
+ }),
+ );
+ expect(log).toEqual([
+ ['capture', 'grand'],
+ ['capture', 'parent'],
+ ['capture', 'child'],
+ ['bubble', 'child'],
+ ]);
+ } finally {
+ document.body.removeChild(container);
+ }
+ });
+
+ // Regression test.
+ it('should subscribe to scroll during hydration', () => {
+ const container = document.createElement('div');
+ const ref = React.createRef();
+ const log = [];
+ const onScroll = jest.fn(e =>
+ log.push(['bubble', e.currentTarget.className]),
+ );
+ const onScrollCapture = jest.fn(e =>
+ log.push(['capture', e.currentTarget.className]),
+ );
+ const tree = (
+
+ );
+ document.body.appendChild(container);
+ try {
+ container.innerHTML = ReactDOMServer.renderToString(tree);
+ ReactDOM.hydrate(tree, container);
+ ref.current.dispatchEvent(
+ new Event('scroll', {
+ bubbles: false,
+ }),
+ );
+ expect(log).toEqual([
+ ['capture', 'grand'],
+ ['capture', 'parent'],
+ ['capture', 'child'],
+ ['bubble', 'child'],
+ ]);
+ } finally {
+ document.body.removeChild(container);
+ }
+ });
});
diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js
index 48b979af64c94..a228b15647945 100644
--- a/packages/react-dom/src/client/ReactDOMComponent.js
+++ b/packages/react-dom/src/client/ReactDOMComponent.js
@@ -1086,6 +1086,8 @@ export function diffHydratedProperties(
}
if (!enableEagerRootListeners) {
ensureListeningTo(rootContainerElement, propKey, domElement);
+ } else if (propKey === 'onScroll') {
+ listenToNonDelegatedEvent('scroll', domElement);
}
}
} else if (