You can take a subset of messages at a time for render, and then queue up further updates with more children via a count in state.
Using requestIdleCallback or setTimeout to queue will allow you to escape React's state batching from intercepting the current browser paint, which would be a problem if you did setState directly from componentDidUpdate
Heres something to get you going
const Parent = React.createClass({ numMessagesPerRender = 10 constructor(props) { super(props) this.state = { renderedCount: 0 } } componentWillReceiveProps(props) { // must check that if the messages change, and reset count if you do // you may also need to do a deep equality of values if you mutate the message elsewhere if (props.messages !== this.props.messages) { this.setState({renderedCount: 0}) } } getChildren() { // take only the current const children = this.props.messages.slice(0, this.state.renderedCount); return children.map(child => <FooBar c={child} />); }, render() { return ( <div> {this.getChildren()} </div> ); } renderMoreMessagesPlease() { // you MUST include an escape condition as we are calling from `componentDidXYZ` // if you dont your component will get stuck in a render loop and crash if (this.state.renderedCount < this.props.messages.length) { // queue up state change until the frame has been painted // otherwise setState can halt rendering to do batching of state changes into a single // if your browser doesnt support requestIdleCallback, setTimeout should do same trick this.idleCallbackId = requestIdleCallback(() => this.setState(prevState => ({ renderedCount: prevState.renderedCount + this.numMessagesPerRender }))) } } componentDidMount() { this.renderMoreMessagesPlease() } componentDidUpdate() { this.renderMoreMessagesPlease() } componentDidUnmount() { // clean up so cant call setState on an unmounted component if (this.idleCallbackId) { window.cancelIdleCallback(this.idleCallbackId) } } });