每次将新元素推入列表时,列表的 ReactJS 渲染时间都会增加
Posted
技术标签:
【中文标题】每次将新元素推入列表时,列表的 ReactJS 渲染时间都会增加【英文标题】:ReactJS render time of list increases each time new elements pushed into the list 【发布时间】:2016-04-25 00:35:49 【问题描述】:我正在尝试使用 react js 呈现项目列表。由于我的列表项相对复杂,我创建了一个简单的小提琴来说明我的问题。
fiddle
在我的情况下,我有无限滚动的帖子,并且每次推送帖子都会很快超出合理的渲染时间,从而增加渲染时间。它从 200-250 毫秒开始,在 10 次推送后达到 500 毫秒(每次推送有 0-10 个帖子)。
如何修复新添加项目的渲染时间?或者这只是反应 js 的工作方式。
这是我的主要 ReactComponent 简化版。
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>);
);
此时 ReactStreamPost 和 ReactStreamActivity 可以是无状态组件。喜欢
var ReactStreamPost = React.createClass(
shouldComponentUpdate: function ()
return false;
,
render: function ()
return (
<div className="stream-post">
<div className="post-topbar">
<a 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 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 href="#">
<i className="icon icon-add-info"></i><span>Add info</span>
</a>
</div>
<div className="right-actions">
<a href="#" className="toggler">
<i className="icon"></i>
<span>x</span>
</a>
<a href="#" className="toggler">
<i className="icon"></i>
<span>x</span>
</a>
<a 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 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 href="#" className="icon icon-send"></a>
</div>
</div>
</div>
</div>
</div>
<div className="post-date">
<span>post date</span>
</div>
</div>
);
);
【问题讨论】:
你添加更多的 DOM 元素当然会增加时间。 但是每次我向 dom 添加相同数量的元素。我知道每次状态更新都会重新渲染,但这个成本对我来说似乎有点高。 请不要使用数组索引作为子元素键。如果您使用在将其他内容添加到列表时不会更改的键,您将获得更好的性能。 【参考方案1】:这是因为每次添加更多元素时,都会重新渲染整个列表,其中还包括之前已经渲染过的列表项。
一种解决方法是将列表项放在它自己的组件中,并使用 shouldComponentUpdate 不重新渲染它。这仍然会增加时间,因为它仍然需要检查是否需要重新渲染,但增量不会那么陡峭。一个工作小提琴here。您的行组件将如下所示:-
var Row = React.createClass(
shouldComponentUpdate: function()
return false;
,
render: function()
return ( < li > < span > some < /span><span>more</span > < span > elements < /span></li > )
)
【讨论】:
这是我在自己的实现中尝试做的,但要重新检查它。谢谢你的例子。 jsfiddle.net/jain208/3jj5Loky/3 - 这是两个实现的更新小提琴。 :-) 但是是的,这种方法永远不会有效,因为您仍在渲染大量项目。理想的方法是只显示列表的一个子集。以上是关于每次将新元素推入列表时,列表的 ReactJS 渲染时间都会增加的主要内容,如果未能解决你的问题,请参考以下文章