简体   繁体   English

父组件上的ReactJS事件驱动更新

[英]ReactJS event-driven updates on parent component

I have some components that are buried deep inside their parents. 我的一些组件深深地埋在父母的内心。 I have a user variable, which is fetched at the absolute top of this chain (a ProfilePage component), and passed all the way down with props. 我有一个用户变量,该变量在此链的绝对顶部( ProfilePage组件)获取,并一直通过props传递。 But, sometimes the user updates its profile in a small component on the page (the AboutMe component for example). 但是,有时用户会在页面上的一个AboutMe件(例如AboutMe组件)中更新其个人资料。 My current flow is to have the AboutMe component update the user via ajax, and then trigger an event called 'profileupdate' on my pubsub. 我当前的流程是让AboutMe组件通过ajax更新用户,然后在我的pubsub上触发一个名为“ profileupdate”的事件。 When 'profileupdate' is triggered, the ProfilePage fetches the user again via ajax, and so all the props are updated. 当触发“ profileupdate”时, ProfilePage通过ajax再次获取用户,因此所有道具都将更新。 This tactic appears to work, but it almost always gives: 这种策略似乎有效,但几乎总是可以做到:

Uncaught Error: Invariant Violation: replaceState(...): Can only update a mounted or mounting component.

I know this error is coming from the ProfilePage not being mounted and replacing its user state. 我知道此错误是由于未装入ProfilePage并替换其用户状态引起的。

Here is an example of a place where I do this: 这是我执行此操作的地方的示例:

In the ProfilePage component: ProfilePage组件中:

var ProfilePage = React.createClass({
  getInitialState: function() {
    return {};
  },

  updateUser: function() {
    this.setUser('/api/users/' + this.props.params.userId);
  },

  setCurrentUser: function(currentUser) {
    this.setState({ currentUser: currentUser });
  },

  resetCurrentUser: function() {
    auth.getCurrentUser.call(this, this.setCurrentUser);
  },

  componentWillReceiveProps: function(newProps) {
    this.setUser('/api/users/' + newProps.params.userId);
  },

  componentDidMount: function() {
    PubSub.subscribe('profileupdate', this.updateUser);
    PubSub.subscribe('profileupdate', this.resetCurrentUser);
    this.resetCurrentUser();
    this.updateUser();
  },

  setUser: function(url) {
    $.ajax({
      url: url,
      success: function(user) {
        if (this.isMounted()) {
          this.setState({ user: user });
        } else {
          console.log("ProfilePage not mounted.");
        }  
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.userId, status, err.toString());
      }.bind(this)
    });
  },

Then, in the AboutInput component: ProfilePage --> ProfileBox --> About --> AboutInput 然后,在AboutInput组件中:ProfilePage-> ProfileBox-> About-> AboutInput

updateAbout: function(text) {
  var url = '/api/users/' + this.props.user._id;
  var user = this.props.user;
  user.about = text;
  $.ajax({
    url: url,
    type: 'PUT',
    data: user,
    success: function(user) {
      auth.storeCurrentUser(user, function(user) {
        return user;
      });
      PubSub.publish('profileupdate');
      this.propagateReset();
    }.bind(this),
    error: function(xhr, status, err) {
      console.error(status, err.toString());
      this.propagateReset();
    }.bind(this)
  });
},

The takeaways here are that the ProfilePage fetches the user again when the profileupdate event is triggered. 这里的要点是,当触发profileupdate事件时,ProfilePage再次获取用户。

Am I using the wrong tactics here? 我在这里使用错误的策略吗? How can I handle this kind of update? 我该如何处理这种更新? And, can I force the ProfilePage to become mounted? 而且,我可以强制ProfilePage挂载吗? That would be really ideal. 那真的很理想。 Also, interestingly, whether or not the console logs that the ProfilePage is unmounted, the user still updates. 同样,有趣的是,无论控制台是否记录了ProfilePage已卸载,用户仍然会更新。

I really would take a look at Facebook's FLUX implementation. 我真的会看一下Facebook的FLUX实现。 It will simplify your workflow tremendously. 它将极大地简化您的工作流程。 I am guessing that is not an option at this moment, but make sure your components are unsubscribing when removing them. 我猜这不是目前的选择,但请确保在删除组件时取消订阅。 For eg: 例如:

componentWillUnmount: function () {
    var self = this;
    self.store.removeListener('change', self._setState);
    self._setState = null;
}

Or in your case unsubscribe using the method above from your PubSub implementation when a component is being replaced. 或者,在更换组件时,使用您的PubSub实现中的上述方法取消订阅。 So 'profileupdate' is being called on a React component that has been unmounted. 因此,在已卸载的React组件上调用了“ profileupdate”。 Something like. 就像是。

componentWillUnmount: function () {
    PubSub.unsubscribe('profileupdate', this.updateUser);
    PubSub.unsubscribe('profileupdate', this.resetCurrentUser);
    this.updateUser = null;
    this.resetCurrentUser = null;
}

It is exactly what the error states. 这正是错误所指出的。 You trying to set state on a React component that is not longer mounted, or has been removed. 您试图在不再安装或已被移除的React组件上设置状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM