Skip to content

Instantly share code, notes, and snippets.

@sjednac
Created July 3, 2018 12:21
Show Gist options
  • Save sjednac/bff384efc3c745967adc60d88af07604 to your computer and use it in GitHub Desktop.
Save sjednac/bff384efc3c745967adc60d88af07604 to your computer and use it in GitHub Desktop.
A React component which renders it's children sequentially with a fixed period (PoC)
import React from 'react'
import PropTypes from 'prop-types'
import {
isEqual,
includes
} from 'lodash'
class DelayedList extends React.Component {
constructor(props) {
super(props)
this.state = { visibleItems: [], waitingItems: [] }
this.timers = []
}
componentDidMount() {
this.appendComponents()
}
componentDidUpdate() {
this.appendComponents()
}
shouldComponentUpdate(nextProps, nextState) {
if (!isEqual(this.props.children, nextProps.children)) {
this.cancelAllTimers()
this.setState({visibleItems: [], waitingItems: []})
return true;
}
return !isEqual(this.state.visibleItems, nextState.visibleItems)
}
componentWillUnmount() {
this.cancelAllTimers()
this.setState({visibleItems: [], waitingItems: []})
}
appendComponents() {
if (this.props.active !== null && !this.props.active) {
this.cancelAllTimers()
this.setState({visibleItems: this.props.children, waitingItems: []})
return
}
const newComponents = this.newChildren()
const delay = this.props.delay || 1000
this.setState({ waitingItems: [...this.state.waitingItems, ...newComponents]})
const newTimers = newComponents.map( (component, index) => {
const appendItem = () => {
this.setState({
visibleItems: [...this.state.visibleItems, component],
waitingItems: this.state.waitingItems.filter( (waitingItem) => !isEqual(waitingItem, component))
})
}
return setTimeout(appendItem.bind(this), delay + index * delay)
})
this.timers = this.timers.concat(newTimers)
}
newChildren() {
return this.props.children.filter( (child) =>
!includes(this.state.visibleItems, child) &&
!includes(this.state.waitingItems, child)
)
}
cancelAllTimers() {
this.timers.forEach( (timer) => {
if (timer) {
clearTimeout(timer)
}
})
this.timers = []
}
render() {
return (
<div className="delayed-list">
{this.state.visibleItems}
</div>
)
}
}
DelayedList.propTypes = {
delay: PropTypes.number,
active: PropTypes.bool
}
export default DelayedList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment