Listen to onScroll during hydration (#19803)
Dan Abramov committed
Sep 10, 2020 at 11:00 UTC
a08ae9f147a716520a089055e2dec8f5397a4b0f
2 files changed
+108
packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
+106
@@ -12,11 +12,13 @@
12
describe('ReactDOMEventListener', () => {
13
let React;
14
let ReactDOM;
15
+ let ReactDOMServer;
16
17
beforeEach(() => {
18
jest.resetModules();
19
React = require('react');
20
ReactDOM = require('react-dom');
21
+ ReactDOMServer = require('react-dom/server');
22
});
23
24
describe('Propagation', () => {
@@ -797,4 +799,108 @@ describe('ReactDOMEventListener', () => {
799
document.body.removeChild(container);
800
}
801
});
802
+
803
+ it('should subscribe to scroll during updates', () => {
804
+ const container = document.createElement('div');
805
+ const ref = React.createRef();
806
+ const log = [];
807
+ const onScroll = jest.fn(e =>
808
+ log.push(['bubble', e.currentTarget.className]),
809
+ );
810
+ const onScrollCapture = jest.fn(e =>
811
+ log.push(['capture', e.currentTarget.className]),
812
+ );
813
+ document.body.appendChild(container);
814
+ try {
815
+ ReactDOM.render(
816
+ <div>
817
+ <div>
818
+ <div />
819
+ </div>
820
+ </div>,
821
+ container,
822
+ );
823
+ ReactDOM.render(
824
+ <div
825
+ className="grand"
826
+ onScroll={onScroll}
827
+ onScrollCapture={onScrollCapture}>
828
+ <div
829
+ className="parent"
830
+ onScroll={onScroll}
831
+ onScrollCapture={onScrollCapture}>
832
+ <div
833
+ className="child"
834
+ onScroll={onScroll}
835
+ onScrollCapture={onScrollCapture}
836
+ ref={ref}
837
+ />
838
+ </div>
839
+ </div>,
840
+ container,
841
+ );
842
+ ref.current.dispatchEvent(
843
+ new Event('scroll', {
844
+ bubbles: false,
845
+ }),
846
+ );
847
+ expect(log).toEqual([
848
+ ['capture', 'grand'],
849
+ ['capture', 'parent'],
850
+ ['capture', 'child'],
851
+ ['bubble', 'child'],
852
+ ]);
853
+ } finally {
854
+ document.body.removeChild(container);
855
+ }
856
+ });
857
+
858
+ // Regression test.
859
+ it('should subscribe to scroll during hydration', () => {
860
+ const container = document.createElement('div');
861
+ const ref = React.createRef();
862
+ const log = [];
863
+ const onScroll = jest.fn(e =>
864
+ log.push(['bubble', e.currentTarget.className]),
865
+ );
866
+ const onScrollCapture = jest.fn(e =>
867
+ log.push(['capture', e.currentTarget.className]),
868
+ );
869
+ const tree = (
870
+ <div
871
+ className="grand"
872
+ onScroll={onScroll}
873
+ onScrollCapture={onScrollCapture}>
874
+ <div
875
+ className="parent"
876
+ onScroll={onScroll}
877
+ onScrollCapture={onScrollCapture}>
878
+ <div
879
+ className="child"
880
+ onScroll={onScroll}
881
+ onScrollCapture={onScrollCapture}
882
+ ref={ref}
883
+ />
884
+ </div>
885
+ </div>
886
+ );
887
+ document.body.appendChild(container);
888
+ try {
889
+ container.innerHTML = ReactDOMServer.renderToString(tree);
890
+ ReactDOM.hydrate(tree, container);
891
+ ref.current.dispatchEvent(
892
+ new Event('scroll', {
893
+ bubbles: false,
894
+ }),
895
+ );
896
+ expect(log).toEqual([
897
+ ['capture', 'grand'],
898
+ ['capture', 'parent'],
899
+ ['capture', 'child'],
900
+ ['bubble', 'child'],
901
+ ]);
902
+ } finally {
903
+ document.body.removeChild(container);
904
+ }
905
+ });
906
});
packages/react-dom/src/client/ReactDOMComponent.js
+2
@@ -1086,6 +1086,8 @@ export function diffHydratedProperties(
1086
}
1087
if (!enableEagerRootListeners) {
1088
ensureListeningTo(rootContainerElement, propKey, domElement);
1089
+ } else if (propKey === 'onScroll') {
1090
+ listenToNonDelegatedEvent('scroll', domElement);
1091
}
1092
}
1093
} else if (