React - вызов функции из одноуровневого компонента - PullRequest
0 голосов
/ 14 декабря 2018

Допустим, у меня есть дерево компонентов следующим образом

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

Где SelectableGroup может выбрать / отменить выбор элементов, которые он содержит, с помощью мыши.Я сохраняю текущее выделение (массив выбранных элементов) в хранилище с избыточностью, чтобы все компоненты моего приложения могли его прочитать.

Компонент 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() в Content, а затем немедленно отправьте другое действие, чтобы сбросить это состояние "запроса на очистку выбора"?
  • Или есть какой-либо предпочтительный способ вызова функций родных братьев?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Я думаю, что контекстный API пригодится в этой ситуации.Я часто использовал его в тех случаях, когда использование глобального состояния / редукса казалось неправильным, или когда вы пропускали реквизиты через несколько уровней в дереве компонентов.

Рабочий пример:

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), не забудьте импортировать Context из main.js

0 голосов
/ 14 декабря 2018

Вы можете использовать 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...