Skip to content

Commit 8664305

Browse files
Support delayed stabilisation for simple list
In order to allow items animation
1 parent a74282d commit 8664305

File tree

5 files changed

+85
-34
lines changed

5 files changed

+85
-34
lines changed

examples/index.es6

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ const examples = [
5656
length: 10000,
5757
itemRenderer: renderVariableHeightItem
5858
},
59+
{
60+
length: 10000,
61+
itemRenderer: renderVariableHeightItem,
62+
className: 'is-animated',
63+
stableFrameDelay: 500
64+
},
5965
{
6066
axis: 'x',
6167
length: 10000,
@@ -126,9 +132,13 @@ const examples = [
126132
export default class extends React.Component {
127133
renderExamples() {
128134
return examples.map((props, key) =>
129-
<div key={key} className={`example axis-${props.axis}`}>
135+
<div key={key}
136+
className={`example axis-${props.axis} ${props.className}`}
137+
>
130138
<strong>Props</strong>
131-
<pre className='props'>{JSON.stringify(props, null, 2)}</pre>
139+
<pre className='props'>{
140+
JSON.stringify(props, null, 2).replace(/\\n\s+/g, ' ')
141+
}</pre>
132142
<strong>Component</strong>
133143
<div className='component'><ReactList {...props} /></div>
134144
</div>

examples/index.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@
159159
var examples = [{
160160
length: 10000,
161161
itemRenderer: renderVariableHeightItem
162+
}, {
163+
length: 10000,
164+
itemRenderer: renderVariableHeightItem,
165+
className: 'is-animated',
166+
stableFrameDelay: 500
162167
}, {
163168
axis: 'x',
164169
length: 10000,
@@ -230,7 +235,9 @@
230235
return examples.map(function (props, key) {
231236
return _react2.default.createElement(
232237
'div',
233-
{ key: key, className: 'example axis-' + props.axis },
238+
{ key: key,
239+
className: 'example axis-' + props.axis + ' ' + props.className
240+
},
234241
_react2.default.createElement(
235242
'strong',
236243
null,
@@ -239,7 +246,7 @@
239246
_react2.default.createElement(
240247
'pre',
241248
{ className: 'props' },
242-
JSON.stringify(props, null, 2)
249+
JSON.stringify(props, null, 2).replace(/\\n\s+/g, ' ')
243250
),
244251
_react2.default.createElement(
245252
'strong',

index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@
8282
.even {
8383
background: linear-gradient(#ddd, #ccc);
8484
}
85+
86+
@keyframes grow {
87+
0% { max-height: 0; }
88+
100% { max-height: 120px; }
89+
}
90+
91+
.is-animated .item {
92+
line-height: 120px;
93+
overflow: hidden;
94+
animation: grow 0.5s ease 0s;
95+
}
8596
</style>
8697
</head>
8798

react-list.es6

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module.exports = class ReactList extends Component {
5757
minSize: PropTypes.number,
5858
pageSize: PropTypes.number,
5959
scrollParentGetter: PropTypes.func,
60+
stableFrameDelay: PropTypes.number,
6061
threshold: PropTypes.number,
6162
type: PropTypes.oneOf(['simple', 'variable', 'uniform']),
6263
useStaticSize: PropTypes.bool,
@@ -90,6 +91,7 @@ module.exports = class ReactList extends Component {
9091

9192
componentWillReceiveProps(next) {
9293
let {from, size, itemsPerRow} = this.state;
94+
clearTimeout(this.updateFrameTimeoutId);
9395
this.maybeSetState(this.constrain(from, size, itemsPerRow, next), NOOP);
9496
}
9597

@@ -100,6 +102,7 @@ module.exports = class ReactList extends Component {
100102
}
101103

102104
componentDidUpdate() {
105+
let {stableFrameDelay, type} = this.props;
103106

104107
// If the list has reached an unstable state, prevent an infinite loop.
105108
if (this.unstable) return;
@@ -116,7 +119,14 @@ module.exports = class ReactList extends Component {
116119
}, 0);
117120
}
118121

119-
this.updateFrame();
122+
if (type === 'simple' && stableFrameDelay) {
123+
this.updateFrameTimeoutId = setTimeout(
124+
this.updateFrame, stableFrameDelay
125+
);
126+
} else {
127+
this.updateFrame();
128+
}
129+
120130
}
121131

122132
maybeSetState(b, cb) {
@@ -129,6 +139,7 @@ module.exports = class ReactList extends Component {
129139
window.removeEventListener('resize', this.updateFrame);
130140
this.scrollParent.removeEventListener('scroll', this.updateFrame, PASSIVE);
131141
this.scrollParent.removeEventListener('mousewheel', NOOP, PASSIVE);
142+
clearTimeout(this.updateFrameTimeoutId);
132143
}
133144

134145
getOffset(el) {

react-list.js

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
size = _state.size,
151151
itemsPerRow = _state.itemsPerRow;
152152

153+
clearTimeout(this.updateFrameTimeoutId);
153154
this.maybeSetState(this.constrain(from, size, itemsPerRow, next), NOOP);
154155
}
155156
}, {
@@ -164,6 +165,11 @@
164165
value: function componentDidUpdate() {
165166
var _this2 = this;
166167

168+
var _props = this.props,
169+
stableFrameDelay = _props.stableFrameDelay,
170+
type = _props.type;
171+
172+
167173
// If the list has reached an unstable state, prevent an infinite loop.
168174
if (this.unstable) return;
169175

@@ -179,7 +185,11 @@
179185
}, 0);
180186
}
181187

182-
this.updateFrame();
188+
if (type === 'simple' && stableFrameDelay) {
189+
this.updateFrameTimeoutId = setTimeout(this.updateFrame, stableFrameDelay);
190+
} else {
191+
this.updateFrame();
192+
}
183193
}
184194
}, {
185195
key: 'maybeSetState',
@@ -194,6 +204,7 @@
194204
window.removeEventListener('resize', this.updateFrame);
195205
this.scrollParent.removeEventListener('scroll', this.updateFrame, PASSIVE);
196206
this.scrollParent.removeEventListener('mousewheel', NOOP, PASSIVE);
207+
clearTimeout(this.updateFrameTimeoutId);
197208
}
198209
}, {
199210
key: 'getOffset',
@@ -210,9 +221,9 @@
210221
}, {
211222
key: 'getScrollParent',
212223
value: function getScrollParent() {
213-
var _props = this.props,
214-
axis = _props.axis,
215-
scrollParentGetter = _props.scrollParentGetter;
224+
var _props2 = this.props,
225+
axis = _props2.axis,
226+
scrollParentGetter = _props2.scrollParentGetter;
216227

217228
if (scrollParentGetter) return scrollParentGetter();
218229
var el = findDOMNode(this);
@@ -276,9 +287,9 @@
276287
}, {
277288
key: 'hasDeterminateSize',
278289
value: function hasDeterminateSize() {
279-
var _props2 = this.props,
280-
itemSizeGetter = _props2.itemSizeGetter,
281-
type = _props2.type;
290+
var _props3 = this.props,
291+
itemSizeGetter = _props3.itemSizeGetter,
292+
type = _props3.type;
282293

283294
return type === 'uniform' || itemSizeGetter;
284295
}
@@ -298,9 +309,9 @@
298309
}, {
299310
key: 'getItemSizeAndItemsPerRow',
300311
value: function getItemSizeAndItemsPerRow() {
301-
var _props3 = this.props,
302-
axis = _props3.axis,
303-
useStaticSize = _props3.useStaticSize;
312+
var _props4 = this.props,
313+
axis = _props4.axis,
314+
useStaticSize = _props4.useStaticSize;
304315
var _state2 = this.state,
305316
itemSize = _state2.itemSize,
306317
itemsPerRow = _state2.itemsPerRow;
@@ -377,9 +388,9 @@
377388

378389
if (elEnd > end) return cb();
379390

380-
var _props4 = this.props,
381-
pageSize = _props4.pageSize,
382-
length = _props4.length;
391+
var _props5 = this.props,
392+
pageSize = _props5.pageSize,
393+
length = _props5.length;
383394

384395
var size = Math.min(this.state.size + pageSize, length);
385396
this.maybeSetState({ size: size }, cb);
@@ -393,9 +404,9 @@
393404
start = _getStartAndEnd2.start,
394405
end = _getStartAndEnd2.end;
395406

396-
var _props5 = this.props,
397-
length = _props5.length,
398-
pageSize = _props5.pageSize;
407+
var _props6 = this.props,
408+
length = _props6.length,
409+
pageSize = _props6.pageSize;
399410

400411
var space = 0;
401412
var from = 0;
@@ -490,11 +501,11 @@
490501
value: function getSizeOf(index) {
491502
var cache = this.cache,
492503
items = this.items;
493-
var _props6 = this.props,
494-
axis = _props6.axis,
495-
itemSizeGetter = _props6.itemSizeGetter,
496-
itemSizeEstimator = _props6.itemSizeEstimator,
497-
type = _props6.type;
504+
var _props7 = this.props,
505+
axis = _props7.axis,
506+
itemSizeGetter = _props7.itemSizeGetter,
507+
itemSizeEstimator = _props7.itemSizeEstimator,
508+
type = _props7.type;
498509
var _state4 = this.state,
499510
from = _state4.from,
500511
itemSize = _state4.itemSize,
@@ -582,9 +593,9 @@
582593
value: function renderItems() {
583594
var _this3 = this;
584595

585-
var _props7 = this.props,
586-
itemRenderer = _props7.itemRenderer,
587-
itemsRenderer = _props7.itemsRenderer;
596+
var _props8 = this.props,
597+
itemRenderer = _props8.itemRenderer,
598+
itemsRenderer = _props8.itemsRenderer;
588599
var _state6 = this.state,
589600
from = _state6.from,
590601
size = _state6.size;
@@ -599,11 +610,11 @@
599610
}, {
600611
key: 'render',
601612
value: function render() {
602-
var _props8 = this.props,
603-
axis = _props8.axis,
604-
length = _props8.length,
605-
type = _props8.type,
606-
useTranslate3d = _props8.useTranslate3d;
613+
var _props9 = this.props,
614+
axis = _props9.axis,
615+
length = _props9.length,
616+
type = _props9.type,
617+
useTranslate3d = _props9.useTranslate3d;
607618
var _state7 = this.state,
608619
from = _state7.from,
609620
itemsPerRow = _state7.itemsPerRow;
@@ -653,6 +664,7 @@
653664
minSize: _propTypes2.default.number,
654665
pageSize: _propTypes2.default.number,
655666
scrollParentGetter: _propTypes2.default.func,
667+
stableFrameDelay: _propTypes2.default.number,
656668
threshold: _propTypes2.default.number,
657669
type: _propTypes2.default.oneOf(['simple', 'variable', 'uniform']),
658670
useStaticSize: _propTypes2.default.bool,

0 commit comments

Comments
 (0)