Ad

ReactJS Render Time Of List Increases Each Time New Elements Pushed Into The List

- 1 answer

I am trying to render a list of items with react js. Since my list items relatively complicated I have created a simple fiddle to state my problem.

fiddle

In my case I have an infinite scroll of posts and increasing render time with each push of posts going out of reasonable render times really quick. it starts with 200-250 ms and goes up to 500ms after like 10 pushes (each push has 0-10 posts).

How can I fix the render time of newly added items? or is it just how the react js work.

Here is my main ReactComponent simplified.

React.createClass({
    shouldComponentUpdate: function (nextProps, nextState) {
        return nextState.posts.length !== this.state.posts.length;
    },
    getInitialState: function () {
        return {
            posts: []
        };
    },
    // getStream is bound to a scroll event handler. Simply, this function is called when user gets close to the end of page.
    getStream: function () {
        var self = this;
        ... ajax call success: (jsonResult) ...
        self.setState({
            posts: React.addons.update(self.state.posts, { $push: jsonResult })
        });
        ... end ....
    },
    render: function () {
        var self = this;

        var postNode = this.state.posts.map(function (post, i) {
            if (post.isActivity) {
                return (<ReactActivity key={i}></ReactActivity>);
            }
            else {
                return (<ReactStreamPost key={i}></ReactStreamPost>);
            }
        });

        return (<div>
            {postNode}
        </div>);
    }
    });

And ReactStreamPost and ReactStreamActivity can be stateless components at this point. like

var ReactStreamPost = React.createClass({
    shouldComponentUpdate: function () {
        return false;
    },
    render: function () {
        return (
            <div className="stream-post">
                <div className="post-topbar">
                    <a target="_blank" rel="nofollow noreferrer" href="#" className="display-name">Test USER</a>
                </div>

                <div className="post-inner-wrapper">
                    <div className="post-owner-big">
                        <div className="post-owner">
                            <img className="profile-img" />
                        </div>
                    </div>
                    <div className="post-content">
                        <div className="post-header">
                            <div className="post-owner">
                                <img className="profile-img" />
                            </div>
                            <div className="post-agt">
                                <ReactAutoGenerateTitle></ReactAutoGenerateTitle>
                            </div>
                        </div>
                        <div className="post-title">
                            <div>
                                <a target="_blank" rel="nofollow noreferrer" href="#" className="display-name">Test USER</a><span> Post title</span>
                            </div>
                        </div>
                        <div className="attachments">
                            attachments
                        </div>

                        <div className="post-actions">
                            <div className="left-actions">
                                <a target="_blank" rel="nofollow noreferrer" href="#">
                                    <i className="icon icon-add-info"></i><span>Add info</span>
                                </a>
                            </div>
                            <div className="right-actions">
                                <a target="_blank" rel="nofollow noreferrer" href="#" className="toggler">
                                    <i className="icon"></i>
                                    <span>x</span>
                                </a>
                                <a target="_blank" rel="nofollow noreferrer" href="#" className="toggler">
                                    <i className="icon"></i>
                                    <span>x</span>
                                </a>
                                <a target="_blank" rel="nofollow noreferrer" href="#" className="share icon icon-share"></a>
                            </div>
                        </div>

                        <div className="post-comments">
                            <div className="comment-block">
                                <div className="commentor">
                                    <img />
                                </div>
                                <div className="comment">
                                    <a target="_blank" rel="nofollow noreferrer" href="#">Test USER</a><span>: </span><span>Comment test</span>
                                </div>
                                <div className="comment-date">
                                    <span>comment date</span>
                                </div>
                            </div>

                            <div className="comment-form">
                                <div className="commentor">
                                    <img />
                                </div>
                                <div className="text-area">
                                    <textarea rows="1" className="small"></textarea>
                                </div>
                                <div className="submit-comment">
                                    <a target="_blank" rel="nofollow noreferrer" href="#" className="icon icon-send"></a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="post-date">
                    <span>post date</span>
                </div>
            </div>
        );
    }
});
Ad

Answer

This is because every time you add more elements, the whole list is re-rendered, and that also includes the list items that were already rendered before.

One way to fix is to put the list item in it's own component and use shouldComponentUpdate to not re-render it. This will still increase the time, as it still needs to check whether it needs to re-render or not, but the inxcrease won't be that steep. A working fiddle here. Your row component will look like this:-

  var Row = React.createClass({
  shouldComponentUpdate: function() {
    return false;
  },

  render: function() {
    return ( < li > < span > some < /span><span>more</span > < span > elements < /span></li > )
  }
})
Ad
source: stackoverflow.com
Ad