react-window sync flushes scroll updates
Brian Vaughn committed
Jun 5, 2019 at 14:30 UTC
9d90189ee3129f3a6169fb510ca33bcf69fd200c
1 file changed
+74
-64
vendor/react-window/dist/index.esm.js
+74
-64
@@ -3,6 +3,7 @@ import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
3
import _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';
4
import memoizeOne from 'memoize-one';
5
import { createElement, PureComponent } from 'react';
6
+import { flushSync } from 'react-dom';
7
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';
8
9
// Animation frame based implementation of setTimeout.
@@ -182,37 +183,40 @@ function createGridComponent(_ref2) {
183
scrollTop = _event$currentTarget.scrollTop,
184
scrollWidth = _event$currentTarget.scrollWidth;
185
185
- _this.setState(function (prevState) {
186
- if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
187
- // Scroll position may have been updated by cDM/cDU,
188
- // In which case we don't need to trigger another render,
189
- // And we don't want to update state.isScrolling.
190
- return null;
191
- }
186
+ // Force flush sync for scroll updates to reduce visual checkerboarding.
187
+ flushSync(() => {
188
+ _this.setState(function (prevState) {
189
+ if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
190
+ // Scroll position may have been updated by cDM/cDU,
191
+ // In which case we don't need to trigger another render,
192
+ // And we don't want to update state.isScrolling.
193
+ return null;
194
+ }
195
193
- var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
194
- // Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
195
- // See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
196
+ var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
197
+ // Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
198
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
199
197
- var calculatedScrollLeft = scrollLeft;
200
+ var calculatedScrollLeft = scrollLeft;
201
199
- if (direction === 'rtl') {
200
- if (scrollLeft <= 0) {
201
- calculatedScrollLeft = -scrollLeft;
202
- } else {
203
- calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
202
+ if (direction === 'rtl') {
203
+ if (scrollLeft <= 0) {
204
+ calculatedScrollLeft = -scrollLeft;
205
+ } else {
206
+ calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
207
+ }
208
}
205
- }
209
207
- return {
208
- isScrolling: true,
209
- horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
210
- scrollLeft: calculatedScrollLeft,
211
- scrollTop: scrollTop,
212
- verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
213
- scrollUpdateWasRequested: false
214
- };
215
- }, _this._resetIsScrollingDebounced);
210
+ return {
211
+ isScrolling: true,
212
+ horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
213
+ scrollLeft: calculatedScrollLeft,
214
+ scrollTop: scrollTop,
215
+ verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
216
+ scrollUpdateWasRequested: false
217
+ };
218
+ }, _this._resetIsScrollingDebounced);
219
+ });
220
};
221
222
_this._outerRefSetter = function (ref) {
@@ -1023,55 +1027,61 @@ function createListComponent(_ref) {
1027
scrollLeft = _event$currentTarget.scrollLeft,
1028
scrollWidth = _event$currentTarget.scrollWidth;
1029
1026
- _this.setState(function (prevState) {
1027
- if (prevState.scrollOffset === scrollLeft) {
1028
- // Scroll position may have been updated by cDM/cDU,
1029
- // In which case we don't need to trigger another render,
1030
- // And we don't want to update state.isScrolling.
1031
- return null;
1032
- }
1030
+ // Force flush sync for scroll updates to reduce visual checkerboarding.
1031
+ flushSync(() => {
1032
+ _this.setState(function (prevState) {
1033
+ if (prevState.scrollOffset === scrollLeft) {
1034
+ // Scroll position may have been updated by cDM/cDU,
1035
+ // In which case we don't need to trigger another render,
1036
+ // And we don't want to update state.isScrolling.
1037
+ return null;
1038
+ }
1039
1034
- var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
1035
- // Chrome does not seem to adhere; its scrolLeft values are positive (measured relative to the left).
1036
- // See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
1040
+ var direction = _this.props.direction; // HACK According to the spec, scrollLeft should be negative for RTL aligned elements.
1041
+ // Chrome does not seem to adhere; its scrolLeft values are positive (measured relative to the left).
1042
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
1043
1038
- var scrollOffset = scrollLeft;
1044
+ var scrollOffset = scrollLeft;
1045
1040
- if (direction === 'rtl') {
1041
- if (scrollLeft <= 0) {
1042
- scrollOffset = -scrollOffset;
1043
- } else {
1044
- scrollOffset = scrollWidth - clientWidth - scrollLeft;
1046
+ if (direction === 'rtl') {
1047
+ if (scrollLeft <= 0) {
1048
+ scrollOffset = -scrollOffset;
1049
+ } else {
1050
+ scrollOffset = scrollWidth - clientWidth - scrollLeft;
1051
+ }
1052
}
1046
- }
1053
1048
- return {
1049
- isScrolling: true,
1050
- scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
1051
- scrollOffset: scrollOffset,
1052
- scrollUpdateWasRequested: false
1053
- };
1054
- }, _this._resetIsScrollingDebounced);
1054
+ return {
1055
+ isScrolling: true,
1056
+ scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
1057
+ scrollOffset: scrollOffset,
1058
+ scrollUpdateWasRequested: false
1059
+ };
1060
+ }, _this._resetIsScrollingDebounced);
1061
+ });
1062
};
1063
1064
_this._onScrollVertical = function (event) {
1065
var scrollTop = event.currentTarget.scrollTop;
1066
1060
- _this.setState(function (prevState) {
1061
- if (prevState.scrollOffset === scrollTop) {
1062
- // Scroll position may have been updated by cDM/cDU,
1063
- // In which case we don't need to trigger another render,
1064
- // And we don't want to update state.isScrolling.
1065
- return null;
1066
- }
1067
+ // Force flush sync for scroll updates to reduce visual checkerboarding.
1068
+ flushSync(() => {
1069
+ _this.setState(function (prevState) {
1070
+ if (prevState.scrollOffset === scrollTop) {
1071
+ // Scroll position may have been updated by cDM/cDU,
1072
+ // In which case we don't need to trigger another render,
1073
+ // And we don't want to update state.isScrolling.
1074
+ return null;
1075
+ }
1076
1068
- return {
1069
- isScrolling: true,
1070
- scrollDirection: prevState.scrollOffset < scrollTop ? 'forward' : 'backward',
1071
- scrollOffset: scrollTop,
1072
- scrollUpdateWasRequested: false
1073
- };
1074
- }, _this._resetIsScrollingDebounced);
1077
+ return {
1078
+ isScrolling: true,
1079
+ scrollDirection: prevState.scrollOffset < scrollTop ? 'forward' : 'backward',
1080
+ scrollOffset: scrollTop,
1081
+ scrollUpdateWasRequested: false
1082
+ };
1083
+ }, _this._resetIsScrollingDebounced);
1084
+ });
1085
};
1086
1087
_this._outerRefSetter = function (ref) {