React-从同级组件调用函数

时间:2018-12-14 15:06:17

标签: reactjs react-redux

假设我有一个如下的组件树

<App>
  </Header>
  <Content>
      <SelectableGroup>
          ...items
      </SelectableGroup>
  </Content>
  <Footer />
</App>

SelectableGroup可以通过鼠标选择/取消选择它包含的项目。我正在将当前选择(选定项的数组)存储在redux存储中,以便App中的所有组件都可以读取它。

Content组件已将ref设置为SelectableGroup,这使我能够以编程方式清除选择(调用clearSelection())。像这样:

class Content extends React.Component {

    constructor(props) {
        super(props);
        this.selectableGroupRef = React.createRef();
    }

    clearSelection() {
        this.selectableGroupRef.current.clearSelection();
    }

    render() {
        return (
            <SelectableGroup ref={this.selectableGroupRef}>
                {items}
            </SelectableGroup>
        );
    }

    ...

}

function mapStateToProps(state) {
    ...
}

function mapDispatchToProps(dispatch) {
    ...
}

export default connect(mapStateToProps, mapDispatchToProps)(Content);

我可以轻松地想象将这clearSelection()传递给Content的孩子们。但是,这又是我的问题,我可以从同级组件clearSelection()调用Footer吗?

  • 我应该从Footer派发一个动作,并向Redux商店设置某种“请求调用清除选择”状态吗?在componentDidUpdate()的{​​{1}}回调中对此做出反应,然后立即调度另一个操作来重置此“请求清除选择的请求”状态?
  • 或者有什么首选的方法可以调用兄弟姐妹的函数?

2 个答案:

答案 0 :(得分:0)

您可以像这样使用ref来访问Content组件的全部功能

const { Component } = React;
const { render } = ReactDOM;

class App extends Component {
  render() {
    return (
      <div>
        <Content ref={instance => { this.content = instance; }} />
        <Footer clear={() => this.content.clearSelection() } />
    
      </div>
    );
  }
}

class Content extends Component {
  clearSelection = () => {
    alert('cleared!');
  }

  render() {
    return (
      <h1>Content</h1>
    );
  }
}

class Footer extends Component {

  render() {
    return (
      <div>Footer <button onClick={() => this.props.clear()}>Clear</button>
      </div>
    );
  }
}

render(
  <App />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

答案 1 :(得分:0)

我认为上下文API在这种情况下会派上用场。在使用全局状态/ redux似乎不正确的情况下,或者当您将道具向下传递到组件树中的多个级别时,我开始大量使用它。

工作示例:

import React, { Component } from 'react'
export const Context = React.createContext()

//***************************//

class Main extends Component {

  callback(fn) {
    fn()
  }

  render() {
    return (
      <div>
        <Context.Provider value={{ callback: this.callback }}>
          <Content/>
          <Footer/>
        </Context.Provider>
      </div>
    );
  }
}

export default Main

//***************************//

class Content extends Component {

  render() {

    return (
      <Context.Consumer>
        {(value) => (
          <div onClick={() => value.callback(() => console.log('Triggered from content'))}>Content: Click Me</div>
        )}
      </Context.Consumer>
    )
  }
}

//***************************//

class Footer extends Component {

  render() {

    return (
      <Context.Consumer>
        {(value) => (
          <div onClick={() => value.callback(() => console.log('Triggered from footer'))}>Footer: Click Me</div>
        )}      
      </Context.Consumer>
    )
  }
}

//***************************//

假设内容和页脚以及其中的文件(content.js / footer.js)记住要从main.js导入Context