我有一堆不能具有相同父组件的组件,但是我希望它们共享它们的状态。

为了便于讨论,可以说顶层组件称为Main,子级组件全部称为Child1Child2等。

我有什么办法让Child1Child2成为Main组件的子代,仅在React的意义上-这样我就可以将Main的属性和状态从Main组件传递给它们?

从DOM的 Angular 来看,Child1Child2位于我页面的完全不同的区域中,实际上它们大约有40个。

最佳答案

可以直接使用事件发射器,而不是直接调用setState,并且所有实例都可以将有效负载应用于其状态。

我们可以使用mixin来抽象这种行为。

var makeChangeEventMixin = function(emitter){
   return {
       componentDidMount: function(){
           emitter.addListener('change', this.__makeChangeEventMixin_handler_);
       },
       componentWillUnmount: function(){
           emitter.removeListener('change', this.__makeChangeEventMixin_handler_);
       },
       __makeChangeEventMixin_handler_: function(payload){
           this.setState(payload);
       },
       emitStateChange: function(payload){
           emitter.emit('change', payload);
       }
   };
};

然后在我们的代码中,我们将使用EventEmitter(如果您不使用browserify / webpack,则可以使用EventEmitter2)
var EventEmitter = require('events').EventEmitter;
var fooEvents = new EventEmitter();

var Counter = React.createClass(){
    mixins: [makeChangeEventMixin(fooEvents)],
    getInitialState: function(){ return {count: 0} },
    render: function(){return <div onClick={this.handleClick}>{this.state.count}</div>},
    handleClick: function(){
        this.emitStateChange({count: this.state.count + 1});
    }
};

而且,如果您有100个计数器,则在您单击其中任何一个时,它们都会全部更新。

这样的局限性在于初始状态将是错误的。您可以通过跟踪makeChangeEventMixin中的状态,合并状态为自己,并使用replaceState代替setState来解决此问题。这也会表现得更好。如果这样做,mixin可以实现适当的getInitialState。

10-05 20:17
查看更多