Infinite loop rendering component on ReactJs

I am faced with the problem of an infinite loop, and I do not see what causes it. This happens when rendering components.

I have three components that are organized like this:

TimelineComponent |--PostComponent |--UserPopover 

Timelinecompponenet

 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}); } }); 

Postcomponent

 React.createClass({ ... render: function() { return ( ... <UserPopover userId= {this.props.post.user_id}/> ... ); } }); 

UserPopover

 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) }); } }); 

Finally, there is also a UserStore **:

 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); } }); 

Everything works correctly, except for the UserPopover component.

For each PostComponent , one UserPopOver is created that retrieves the data in the willMount loop.

The fact is that if you notice that I have this line of code console.log(i++); in the UserPopover component, which increments and increments

 ... 3820 3821 3822 3823 3824 3825 ... 

Clean the endless loop, but I really don't know where it comes from. If anyone can give me a hint, I will be very grateful.

PS: I already tried this approach in UsersStore , but then all PostComponent have the same "user":

 ... 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); } ... 

And in UserPopover

 ... onChange: function(event, user) { this.setState({ user: user }); } ... 
+6
source share
2 answers

Since your messages are sent async, I believe that when your UserPopover component executes componentWillMount component, props.userId is undefined, and then you call UsersStore.findUser (this.props.userId), in UserStore, getUser is called because it cannot find user in local storage.

NOTE that each time getUser ajax completes, it starts. Therefore, the UserPopover component performs the onChange function and calls UsersStore.findUser again. This is an endless cycle.

Please add console.log (this.props.userId) in the UserPopover componentWillMount component to see if this looks like what I said above. Actually, I'm not 100% sure.

This is a problem due to the fact that all instances of UserPopover use the same UserStore, I think we should revise the structure of these components and stores. But I have not yet thought out a better way.

+2
source

You can do it as follows:

 TimelineComponent |--PostComponent |--UserPopover 

UserPopover just listens for changes and updates itself.

UserPopover listens for changes to the repository, which stores user data that should be in the popover and the update changes themselves. You can also send coordinates where to visualize. There is no need to create a popover for each message.

+1
source

All Articles