Reactjs父组件与子组件

时间:2016-11-02 10:03:49

标签: reactjs

我使用没有FLux或Redux的ReactJS。我希望grand child组件可以与他的祖父母组件进行通信(读取/更新数据)。

这里是父组件应用

export default class App extends React.Component {
 static propTypes = {
   children: React.PropTypes.object.isRequired
 };

  constructor(props) {
    super(props);
    this.state = {
      tabActive: 0,
    };
  }
  setTabActive(item) {
    this.setState({
      tabActive: item,
    });
  }
  render() {
    return (
      <div>
        <Header tabActive={this.state.tabActive} />
        <Content>
          {this.props.children}
        </ Content>
        <Footer />
      </div>
    );
  }
}

子组件标题

export default class Header extends React.Component {
  render() {
    return (
      <div>
          ....
         <SettingTabBar tabActive={this.props.tabActive} />
      </div>
    );
  }
}

儿童成分的儿童 SettingTabBar

export default class SettingTabBar extends React.Component {
  constructor(props) {
    super(props);
    this.state = { activeTab: this.props.tabActive  };
  }

  render() {
    if (location.pathname.indexOf('setting') > 0) {
      return (
        <Tabs activeTab={this.state.activeTab} onChange={tabId => this.setState({ activeTab: tabId })} ripple>
          <Tab>SETTING</Tab>
          <Tab>CHARTS</Tab>
          <Tab>HELP</Tab>
        </Tabs>
      );
    }
    return null;
  }
}

无论如何,当onChange时,SettingTabBar组件是否可以通过函数 setTabActive()将数据更新到App / Header组件?

1 个答案:

答案 0 :(得分:1)

与祖父母和孙子女的交流,可以使用上下文。它没有被推荐,但它正在发挥作用。

// root component
class App extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            activeMenu: "none"
        };
    }

    getChildContext() {
        return {
            rootCallback: menuName => {
                this.setState({activeMenu: menuName});
            }
        }
    }

    render() {
        return (
          <div>
            <div>Current active menu is: <strong>{this.state.activeMenu}</strong></div>
            <Child />
          </div>
        );
    }
}

// declare childContextTypes at context provider
App.childContextTypes = {
    rootCallback: React.PropTypes.function
}

// intermediate child
class Child extends React.Component {
    render() {
        return (
            <div>
                <GrandChild />
            </div>
        );
    }
}

// grand child
class GrandChild extends React.Component {
    render() {
        return ( 
            <div>
                {/* get context by using this.context */}
                <button 
                    type="button" 
                    onClick={()=>this.context.rootCallback("one")}
                >
                    Activate menu one
                </button>
                <button 
                    type="button" 
                    onClick={()=>this.context.rootCallback("two")}
                >
                    Activate menu two
                </button>
                <button 
                    type="button" 
                    onClick={()=>this.context.rootCallback("three")}
                >
                    Activate menu three
                </button>
            </div>
        )
    }
}

// also declare contextTypes at context consumer
GrandChild.contextTypes = {
     rootCallback: React.PropTypes.function
}

// render it to DOM
ReactDOM.render(<App /> , document.getElementById('app-mount'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app-mount"></div>