@@ -2,7 +2,6 @@ const React           = require('react');
22const  ReactDOM  =  require ( 'react-dom' ) ; 
33const  joinClasses      =  require ( 'classnames' ) ; 
44const  PropTypes        =  React . PropTypes ; 
5- const  shallowEqual     =  require ( 'fbjs/lib/shallowEqual' ) ; 
65const  ScrollShim       =  require ( './ScrollShim' ) ; 
76const  Row              =  require ( './Row' ) ; 
87const  cellMetaDataShape  =  require ( './PropTypeShapes/CellMetaDataShape' ) ; 
@@ -31,14 +30,16 @@ const Canvas = React.createClass({
3130    columns : PropTypes . oneOfType ( [ PropTypes . object ,  PropTypes . array ] ) . isRequired , 
3231    cellMetaData : PropTypes . shape ( cellMetaDataShape ) . isRequired , 
3332    selectedRows : PropTypes . array , 
34-     rowKey : React . PropTypes . string 
33+     rowKey : React . PropTypes . string , 
34+     rowScrollTimeout : React . PropTypes . number 
3535  } , 
3636
3737  getDefaultProps ( )  { 
3838    return  { 
3939      rowRenderer : Row , 
4040      onRows : ( )  =>  { } , 
41-       selectedRows : [ ] 
41+       selectedRows : [ ] , 
42+       rowScrollTimeout : 0 
4243    } ; 
4344  } , 
4445
@@ -62,25 +63,12 @@ const Canvas = React.createClass({
6263  } , 
6364
6465  componentWillReceiveProps ( nextProps : any )  { 
65-     let  scrollbarWidth  =  this . getScrollbarWidth ( ) ; 
66-     let  shouldUpdate  =  ! ( nextProps . visibleStart  >  this . state . displayStart 
67-                         &&  nextProps . visibleEnd  <  this . state . displayEnd ) 
68-                         ||  nextProps . rowsCount  !==  this . props . rowsCount 
69-                         ||  nextProps . rowHeight  !==  this . props . rowHeight 
70-                         ||  nextProps . columns  !==  this . props . columns 
71-                         ||  nextProps . width  !==  this . props . width 
72-                         ||  nextProps . cellMetaData  !==  this . props . cellMetaData 
73-                         ||  ! shallowEqual ( nextProps . style ,  this . props . style ) ; 
74- 
75-     if  ( shouldUpdate )  { 
66+     if  ( nextProps . displayStart  !==  this . state . displayStart 
67+     ||  nextProps . displayEnd  !==  this . state . displayEnd )  { 
7668      this . setState ( { 
77-         shouldUpdate : true , 
7869        displayStart : nextProps . displayStart , 
79-         displayEnd : nextProps . displayEnd , 
80-         scrollbarWidth : scrollbarWidth 
70+         displayEnd : nextProps . displayEnd 
8171      } ) ; 
82-     }  else  { 
83-       this . setState ( { shouldUpdate : false ,  scrollbarWidth : scrollbarWidth } ) ; 
8472    } 
8573  } , 
8674
@@ -112,8 +100,28 @@ const Canvas = React.createClass({
112100    this . appendScrollShim ( ) ; 
113101    let  { scrollTop,  scrollLeft}  =  e . target ; 
114102    let  scroll  =  { scrollTop,  scrollLeft} ; 
103+     // check how far we have scrolled, and if this means we are being taken out of range 
104+     let  scrollYRange  =  Math . abs ( this . _scroll . scrollTop  -  scroll . scrollTop )  /  this . props . rowHeight ; 
105+     let  scrolledOutOfRange  =  scrollYRange  >  ( this . props . displayEnd  -  this . props . displayStart ) ; 
106+ 
115107    this . _scroll  =  scroll ; 
116108    this . props . onScroll ( scroll ) ; 
109+     // if we go out of range, we queue the actual render, just rendering cheap placeholders 
110+     // avoiding rendering anything expensive while a user scrolls down 
111+     if  ( scrolledOutOfRange  &&  this . props . rowScrollTimeout  >  0 )  { 
112+       let  scrollTO  =  this . state . scrollingTimeout ; 
113+       if  ( scrollTO )  { 
114+         clearTimeout ( scrollTO ) ; 
115+       } 
116+      // queue up, and set state to clear the TO so we render the rows (not placeholders) 
117+       scrollTO  =  setTimeout ( ( )  =>  { 
118+         if  ( this . state . scrollingTimeout  !==  null )  { 
119+           this . setState ( { scrollingTimeout : null } ) ; 
120+         } 
121+       } ,  this . props . rowScrollTimeout ) ; 
122+ 
123+       this . setState ( { scrollingTimeout : scrollTO } ) ; 
124+     } 
117125  } , 
118126
119127  getRows ( displayStart : number ,  displayEnd : number ) : Array < any >  { 
@@ -166,6 +174,12 @@ const Canvas = React.createClass({
166174  } , 
167175
168176  renderRow ( props : any )  { 
177+     if  ( this . state . scrollingTimeout  !==  null )  { 
178+       // in the midst of a rapid scroll, so we render placeholders 
179+       // the actual render is then queued (through a timeout) 
180+       // this avoids us redering a bunch of rows that a user is trying to scroll past 
181+       return  this . renderScrollingPlaceholder ( props ) ; 
182+     } 
169183    let  RowsRenderer  =  this . props . rowRenderer ; 
170184    if  ( typeof  RowsRenderer  ===  'function' )  { 
171185      return  < RowsRenderer  { ...props } /> ; 
@@ -176,7 +190,30 @@ const Canvas = React.createClass({
176190    } 
177191  } , 
178192
193+   renderScrollingPlaceholder ( props : any ) : ?ReactElement { 
194+     // here we are just rendering empty cells 
195+     // we may want to allow a user to inject this, and/or just render the cells that are in view 
196+     // for now though we essentially are doing a (very lightweight) row + cell with empty content 
197+     let  styles  =  { 
198+       row : { height : props . height ,  overflow : 'hidden' } , 
199+       cell : { height : props . height ,  position : 'absolute' } , 
200+       placeholder : { backgroundColor : 'rgba(211, 211, 211, 0.45)' ,  width : '60%' ,  height : Math . floor ( props . height  *  0.3 ) } 
201+     } ; 
202+     return  ( 
203+       < div  key = { props . key }  style = { styles . row }  className = "react-grid-Row" > 
204+         { this . props . columns . map ( 
205+           ( col ,  idx )  => 
206+               < div  style = { Object . assign ( styles . cell ,  { width : col . width ,  left : col . left } ) }  key = { idx }  className = "react-grid-Cell" > 
207+                 < div  style = { Object . assign ( styles . placeholder ,  { width : Math . floor ( col . width  *  0.6 ) } ) } > </ div > 
208+               </ div > 
209+         ) } 
210+       </ div > 
211+     ) ; 
212+   } , 
213+ 
179214  renderPlaceholder ( key : string ,  height : number ) : ?ReactElement { 
215+     // just renders empty cells 
216+     // if we wanted to show gridlines, we'd need classes and position as with renderScrollingPlaceholder 
180217    return  ( 
181218      < div  key = { key }  style = { { height : height } } > 
182219        { this . props . columns . map ( 
0 commit comments