ReactJs 上的无限循环渲染组件
Posted
技术标签:
【中文标题】ReactJs 上的无限循环渲染组件【英文标题】:Endless loop rendering component on ReactJs 【发布时间】:2016-02-29 00:35:02 【问题描述】:我正面临一个无限循环问题,我看不到是什么触发了它。它似乎在渲染组件时发生。
我有三个组件,组织如下:
TimelineComponent
|--PostComponent
|--UserPopover
TimelineComponenet:
React.createClass(
mixins: [
Reflux.listenTo(TimelineStore, 'onChange'),
],
getInitialState: function()
return
posts: [],
,
componentWillMount: function()
Actions.getPostsTimeline();
,
render: function()
return (
<div className="timeline">
this.renderPosts()
</div>
);
,
renderPosts: function ()
return this.state.posts.map(function(post)
return (
<PostComponenet key=post.id post=post />
);
);
,
onChange: function(event, posts)
this.setState(posts: posts);
);
后组件:
React.createClass(
...
render: function()
return (
...
<UserPopover userId= this.props.post.user_id/>
...
);
);
用户弹出框:
module.exports = React.createClass(
mixins: [
Reflux.listenTo(UsersStore, 'onChange'),
],
getInitialState: function()
return
user: null
;
,
componentWillMount: function()
Actions.getUser(this.props.userId);
,
render: function()
return (this.state.user? this.renderContent() : null);
,
renderContent: function()
console.log(i++);
return (
<div>
<img src=this.state.user.thumbnail />
<span>this.state.user.name</span>
<span>this.state.user.last_name</span>
...
</div>
);
,
onChange: function()
this.setState(
user: UsersStore.findUser(this.props.userId)
);
);
最后还有UsersStore**:
module.exports = Reflux.createStore(
listenables: [Actions],
users: [],
getUser: function(userId)
return Api.get(url/userId)
.then(function(json)
this.users.push(json);
this.triggerChange();
.bind(this));
,
findUser: function(userId)
var user = _.findWhere(this.users, 'id': userId);
if(user)
return user;
else
this.getUser(userId);
return [];
,
triggerChange: function()
this.trigger('change', this.users);
);
除了 UserPopover 组件外,一切都正常工作。
对于每个 PostComponent 正在渲染一个 UserPopOver,它在 willMount 循环中获取数据。
问题是,如果您注意到我在 UserPopover 组件中有这行代码 console.log(i++);
,它会一遍又一遍地递增
...
3820
3821
3822
3823
3824
3825
...
清除一个无限循环,但我真的不知道它来自哪里。如果有人可以给我一个提示,我将非常感激。
PS:我已经在 UsersStore 中尝试过这种方法,但是所有 PostComponent 都有相同的“用户”:
...
getUser: function(userId)
return Api.get(url/userId)
.then(function(json)
this.user = json;
this.triggerChange();
.bind(this));
,
triggerChange: function()
this.trigger('change', this.user);
...
并且在 UserPopover
...
onChange: function(event, user)
this.setState(
user: user
);
...
【问题讨论】:
非常感谢@ForceMagic 的评论,现在已经很清楚了! 很高兴你喜欢它!在重新整理一些想法的同时,我真的很努力地保留了本质! :) 【参考方案1】:你可以这样做:
TimelineComponent
|--PostComponent
|--UserPopover
UserPopover 只是监听变化并自行更新。
UserPopover 监听 store 中的变化,它保存了哪些用户的数据应该在 popover 中以及变化更新本身。您还可以发送坐标来渲染。无需为每个 Post 创建 Popover。
【讨论】:
【参考方案2】:因为你的帖子是异步获取的,我相信当你的UserPopover组件执行它的componentWillMount时,props.userId是未定义的,然后你调用UsersStore.findUser(this.props.userId),在UserStore中,getUser是调用,因为它在本地存储中找不到用户。
请注意,每次 getUser 的 ajax 完成时,它都会触发。于是UserPopover组件执行onChange函数,再次调用UsersStore.findUser。那是一个无限循环。
请在 UserPopover 的 componentWillMount 中添加一个 console.log(this.props.userId) 以查看它是否像我上面所说的那样。我实际上不是 100% 确定它。
这是所有UserPopover实例共享同一个UserStore的问题,我认为我们应该重新考虑这些组件和存储的结构。但是我还没有想到最好的方法。
【讨论】:
以上是关于ReactJs 上的无限循环渲染组件的主要内容,如果未能解决你的问题,请参考以下文章
控制台上的 Vue 警告:组件渲染函数中可能存在无限更新循环