@@ -2,7 +2,6 @@ const React = require('react');
2
2
const ReactDOM = require ( 'react-dom' ) ;
3
3
const joinClasses = require ( 'classnames' ) ;
4
4
const PropTypes = React . PropTypes ;
5
- const shallowEqual = require ( 'fbjs/lib/shallowEqual' ) ;
6
5
const ScrollShim = require ( './ScrollShim' ) ;
7
6
const Row = require ( './Row' ) ;
8
7
const cellMetaDataShape = require ( './PropTypeShapes/CellMetaDataShape' ) ;
@@ -31,14 +30,16 @@ const Canvas = React.createClass({
31
30
columns : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . array ] ) . isRequired ,
32
31
cellMetaData : PropTypes . shape ( cellMetaDataShape ) . isRequired ,
33
32
selectedRows : PropTypes . array ,
34
- rowKey : React . PropTypes . string
33
+ rowKey : React . PropTypes . string ,
34
+ rowScrollTimeout : React . PropTypes . number
35
35
} ,
36
36
37
37
getDefaultProps ( ) {
38
38
return {
39
39
rowRenderer : Row ,
40
40
onRows : ( ) => { } ,
41
- selectedRows : [ ]
41
+ selectedRows : [ ] ,
42
+ rowScrollTimeout : 0
42
43
} ;
43
44
} ,
44
45
@@ -62,25 +63,12 @@ const Canvas = React.createClass({
62
63
} ,
63
64
64
65
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 ) {
76
68
this . setState ( {
77
- shouldUpdate : true ,
78
69
displayStart : nextProps . displayStart ,
79
- displayEnd : nextProps . displayEnd ,
80
- scrollbarWidth : scrollbarWidth
70
+ displayEnd : nextProps . displayEnd
81
71
} ) ;
82
- } else {
83
- this . setState ( { shouldUpdate : false , scrollbarWidth : scrollbarWidth } ) ;
84
72
}
85
73
} ,
86
74
@@ -112,8 +100,28 @@ const Canvas = React.createClass({
112
100
this . appendScrollShim ( ) ;
113
101
let { scrollTop, scrollLeft} = e . target ;
114
102
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
+
115
107
this . _scroll = scroll ;
116
108
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
+ }
117
125
} ,
118
126
119
127
getRows ( displayStart : number , displayEnd : number ) : Array < any > {
@@ -166,6 +174,12 @@ const Canvas = React.createClass({
166
174
} ,
167
175
168
176
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
+ }
169
183
let RowsRenderer = this . props . rowRenderer ;
170
184
if ( typeof RowsRenderer === 'function' ) {
171
185
return < RowsRenderer { ...props } /> ;
@@ -176,7 +190,30 @@ const Canvas = React.createClass({
176
190
}
177
191
} ,
178
192
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
+
179
214
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
180
217
return (
181
218
< div key = { key } style = { { height : height } } >
182
219
{ this . props . columns . map (
0 commit comments