@@ -80,6 +80,7 @@ module.exports = class ReactList extends Component {
8080 const { from, size} = this . constrain ( initialIndex , 0 , itemsPerRow , props ) ;
8181 this . state = { from, size, itemsPerRow} ;
8282 this . cache = { } ;
83+ this . cachedScroll = null ;
8384 this . prevPrevState = { } ;
8485 this . unstable = false ;
8586 this . updateCounter = 0 ;
@@ -91,8 +92,8 @@ module.exports = class ReactList extends Component {
9192 }
9293
9394 componentDidMount ( ) {
94- this . updateFrame = this . updateFrame . bind ( this ) ;
95- window . addEventListener ( 'resize' , this . updateFrame ) ;
95+ this . updateFrameAndClearCache = this . updateFrameAndClearCache . bind ( this ) ;
96+ window . addEventListener ( 'resize' , this . updateFrameAndClearCache ) ;
9697 this . updateFrame ( this . scrollTo . bind ( this , this . props . initialIndex ) ) ;
9798 }
9899
@@ -123,8 +124,8 @@ module.exports = class ReactList extends Component {
123124 }
124125
125126 componentWillUnmount ( ) {
126- window . removeEventListener ( 'resize' , this . updateFrame ) ;
127- this . scrollParent . removeEventListener ( 'scroll' , this . updateFrame , PASSIVE ) ;
127+ window . removeEventListener ( 'resize' , this . updateFrameAndClearCache ) ;
128+ this . scrollParent . removeEventListener ( 'scroll' , this . updateFrameAndClearCache , PASSIVE ) ;
128129 this . scrollParent . removeEventListener ( 'mousewheel' , NOOP , PASSIVE ) ;
129130 }
130131
@@ -154,6 +155,8 @@ module.exports = class ReactList extends Component {
154155 }
155156
156157 getScroll ( ) {
158+ // Cache scroll position as this causes a forced synchronous layout.
159+ if ( typeof this . cachedScroll === 'number' ) return this . cachedScroll ;
157160 const { scrollParent} = this ;
158161 const { axis} = this . props ;
159162 const scrollKey = SCROLL_START_KEYS [ axis ] ;
@@ -166,7 +169,8 @@ module.exports = class ReactList extends Component {
166169 const max = this . getScrollSize ( ) - this . getViewportSize ( ) ;
167170 const scroll = Math . max ( 0 , Math . min ( actual , max ) ) ;
168171 const el = this . getEl ( ) ;
169- return this . getOffset ( scrollParent ) + scroll - this . getOffset ( el ) ;
172+ this . cachedScroll = this . getOffset ( scrollParent ) + scroll - this . getOffset ( el ) ;
173+ return this . cachedScroll ;
170174 }
171175
172176 setScroll ( offset ) {
@@ -245,6 +249,12 @@ module.exports = class ReactList extends Component {
245249 return { itemSize, itemsPerRow} ;
246250 }
247251
252+ // Called by 'scroll' and 'resize' events, clears scroll position cache.
253+ updateFrameAndClearCache ( cb ) {
254+ this . cachedScroll = null ;
255+ return this . updateFrame ( cb ) ;
256+ }
257+
248258 updateFrame ( cb ) {
249259 this . updateScrollParent ( ) ;
250260 if ( typeof cb != 'function' ) cb = NOOP ;
@@ -260,10 +270,12 @@ module.exports = class ReactList extends Component {
260270 this . scrollParent = this . getScrollParent ( ) ;
261271 if ( prev === this . scrollParent ) return ;
262272 if ( prev ) {
263- prev . removeEventListener ( 'scroll' , this . updateFrame ) ;
273+ prev . removeEventListener ( 'scroll' , this . updateFrameAndClearCache ) ;
264274 prev . removeEventListener ( 'mousewheel' , NOOP ) ;
265275 }
266- this . scrollParent . addEventListener ( 'scroll' , this . updateFrame , PASSIVE ) ;
276+ this . scrollParent . addEventListener ( 'scroll' , this . updateFrameAndClearCache , PASSIVE ) ;
277+ // You have to attach mousewheel listener to the scrollable element.
278+ // Just an empty listener. After that onscroll events will be fired synchronously.
267279 this . scrollParent . addEventListener ( 'mousewheel' , NOOP , PASSIVE ) ;
268280 }
269281
0 commit comments