Компонент рендеринга бесконечного цикла на ReactJs

я столкнулся с проблемой бесконечного цикла, и я не вижу, что его запускает. Кажется, это происходит при рендеринге компонентов.

у меня есть три компонента, организованные следующим образом:

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

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

наконец, есть также 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.

дело в том, если вы заметили, что у меня есть эта строка кода console.log(i++); на UserPopover компонент, который увеличивается снова и снова

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

Clearl бесконечный цикл, но я действительно не знаю, откуда он берется. Если бы кто-нибудь мог дать мне подсказка я буду очень благодарен.

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

2 ответов


поскольку ваши сообщения являются fetch async, я считаю, что при выполнении компонента UserPopover это componentWillMount, реквизит.userId не определен, а затем вы вызываете UsersStore.findUser(это.реквизит.userId), в UserStore getUser вызывается, потому что он не может найти пользователя в локальном хранилище.

обратите внимание, что каждый раз, когда ajax getUser закончил, он срабатывает. Поэтому компонент UserPopover выполнять функцию onChange и вызов UsersStore.снова findUser. Это бесконечная петля.

пожалуйста, добавьте консоль.журнал(это.реквизит.userId) в компоненте UserPopover, чтобы узнать, похоже ли это на то, что я сказал выше. Я на самом деле не уверен на 100%.

это проблема, что все экземпляры UserPopover имеют один и тот же UserStore, я думаю, мы должны переосмыслить структуру этих компонентов и магазинов. Но я еще не придумал лучшего способа.


вы можете сделать это так:

TimelineComponent
   |--PostComponent
   |--UserPopover

UserPopover просто слушайте изменения и обновляйте себя.

UserPopover прослушивает изменения в магазине, который содержит данные пользователя, которые должны быть в popover и при обновлении изменений. Вы также можете отправить координаты, где визуализировать. Нет необходимости создавать Popover для каждого сообщения.