如何在不同组件之间共享状态,而没有任何组件通过任何父子关系相互连接?

时间:2015-11-24 19:34:16

标签: reactjs react-jsx

我是React的新手,我发现它很有趣。我有一个按钮,单击该按钮将在该类中设置一些状态为true,并基于该按钮的标题将更改。 我想根据这种状态变化更改其他类中的其他一些React组件。我怎么能这样做?

例如:

var Comp1 = React.createClass({
    getInitialState: function() {
        return { logged_in: false }
    },

    handleClick: function() {
        this.setState({logged_in: !this.state.logged_in});
    },

    render: function() {
        return <button onClick={this.handleClick}>
                   {this.state.logged_in ? "SIGN OUT" : "SIGN IN"} 
               </button>;
    }

})

这是我的第二个组件,它是单独渲染的。

var Comp2 = React.createClass({
    render: function(){
        return <div>
                   {Comp1.state.logged_in ? "You are in" : "You need a login"}
               </div>;
    }
})

这是一个组成部分。我想通过传递stat来在另一个组件中使用该组件的状态(虽然我没有使用复合格式的组件,因此它们本质上是独立的)或者基于状态的变化我可以定义另一个组件第二部分。

1 个答案:

答案 0 :(得分:2)

您需要提供一个可以处理这两个对象所代表的状态的共享对象。选择标准模型(例如reduxflux)要比提出自己的模型更容易。学习其中一种模式对于React的开发至关重要。我个人推荐redux。

这是一个非常剥离版本的Flux看起来像。它不是一个真正的解决方案,只是为了提供一瞥模式。如果您只想跳到代码,这里是a codepen

共享对象通常称为商店。商店保持状态,并提供订阅该状态变化的方法。改变这种状态通常是通过调用发布带有调度程序的事件来通知商店,但为了简单起见,我在商店本身包含了一个发布功能

let loginStore = {
  isLoggedIn: false,
  _subscribers: new Set(),
  subscribeToLogin(callback) {
    this._subscribers.add(callback);
  },
  unsubscribeToLogin(callback) {
    this._subscribers.delete(callback);
  },
  publishLogin(newState) {
    this.isLoggedIn = newState;
    this._subscribers.forEach(s => s(this.isLoggedIn));
  }
};

一旦发布了pub / sub系统,组件就需要订阅它。登录按钮会改变此状态,因此它也会发布。

class LoginButton extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {isLoggedIn: loginStore.isLoggedIn};
  }
  update = (isLoggedIn) => {
    this.setState({isLoggedIn});
  }
  componentDidMount() {
    loginStore.subscribeToLogin(this.update);
  }
  componentDidUnmount(){
    loginStore.unsubscribeToLogin(this.update);
  }
  handleClick = () => {
    loginStore.publishLogin(!this.state.isLoggedIn);
  }
  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isLoggedIn ? "SIGN OUT" : "SIGN IN"} 
      </button>
    );
  }
}

class LoginHeader extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {isLoggedIn: loginStore.isLoggedIn};
  }
  update = (isLoggedIn) => {
    this.setState({isLoggedIn});
  }
  componentDidMount() {
    loginStore.subscribeToLogin(this.update);
  }
  componentDidUnmount(){
    loginStore.unsubscribeToLogin(this.update);
  }
  render() {
    return (
      <div>{this.state.isLoggedIn ? "You are in" : "You need a login"}</div>
    );
  }
}

您会注意到第二个组件没有引用第一个组件的状态,而是引用了商店的状态。正如您所提到的,由于它们没有相互引用,并且没有共同的父级,因此不能直接相互依赖于loggedIn状态。