Skip to content

Instantly share code, notes, and snippets.

@piecyk
Last active November 18, 2015 17:03
Show Gist options
  • Select an option

  • Save piecyk/74e34f414edea863eab1 to your computer and use it in GitHub Desktop.

Select an option

Save piecyk/74e34f414edea863eab1 to your computer and use it in GitHub Desktop.
Render long list, that has a complex time consuming child elements in async why, break out of react render loop.
// <AsyncRender
// data={[{}, {}, {}]}
// name={'complex'}
// onRender={(el, i) => <TimeConsumingComponent {...el}/>)}
// />
// TODO: know issue, we need to restart the rendering if we got new data,
// when rendering old one still is happening...
// in proper place set pending: false, and bucket: []
const AsyncRender = React.createClass({
pending: false,
bucket: [], // storing tmp elements from this.props.data, then taking one by one and rendering it to dom
mixins: [React.addons.PureRenderIgnoreFunctionsMixin, React.addons.StatePromiseMixin],
getInitialState() {
return {data: []};
},
updateState(el, i) {
return this.setStatePromise({data: (i===0 ? [] : this.state.data).concat(this.props.onRender(el, i))}).then(() => {
if (this.state.data.length === this.props.data.length) {
this.pending = false;
console.debug('finished:', this.props.name, this.pending);
}
});
},
runSyncRender(array, i) {
this.updateState(array.shift(), i).then(() => {
setTimeout(() => {
if (this.bucket.length > 0) {
this.runSyncRender(this.bucket, i+1);
}
}, 0);
});
},
render() {
if (!this.pending) {
_.each(this.props.data, (d, i) => {
this.bucket = this.bucket.concat(d);
if (i === 0) {
setTimeout(() => {
this.pending = true;
this.runSyncRender(this.bucket, i);
}, 0);
}
});
}
return (<span>{this.state.data}</span>);
}
});
module.exports = AsyncRender;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment