Как передать функцию componentDidMount дочерним элементам глубокого слоя в React - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть вопрос о передаче функции componentDidMount от родителя к глубоко лежащему потомку. У меня есть список предметов, которые выбираются по статусу предметов. После того, как я изменил один из статусов элемента, мне нужно повторно сделать родительский элемент, чтобы получить новые данные. Сложность для меня заключается в том, что я не могу найти способ, как передать функцию componentDidMount или действие, чтобы снова получить данные из моего списка.

Мой родительский класс:

class Page extends React.Component {
  componentDidMount() {
    this.props.onCompMount();
  }

  render() {
    const { error, loading, list } = this.props;

    const pageListProps = {
      loading,
      error,
      list,
    };

    return (
      <article>
        <div>
          <PageList {...pageListProps} />
        </div>
      </article>
    );
  }
}

Мой 1-й ребенок:

function PageList({ loading, error, list }) {
  if (loading) {
    return <List component={LoadingIndicator} />;
  }

  if (error !== false) {
    const ErrorComponent = () => (
      <ListItem item="Something went wrong, please try again!" />
    );
    return <List component={ErrorComponent} />;
  }

  if (list !== false) {
    return <List items={list} component={PageItem} />;
  }
  return null;
}

2-й ребенок:

export class PageItem extends React.PureComponent {
  constructor() {
    super();

    this.state = {
      modalIsOpen: false,
    };

    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  openModal() {
    this.setState({ modalIsOpen: true });
  }

  closeModal() {
    this.setState({ modalIsOpen: false });
  }

  render() {
    const { item } = this.props;

    // Put together the content of the repository
    const content = (
      <Wrapper>
        <h3>{item.title}</h3>
        <button onClick={this.openModal}>Decline</button>
        <Modal
          isOpen={this.state.modalIsOpen}
          onRequestClose={this.closeModal}
          style={customStyles}
          contentLabel="Preview"
        >
          <Form close={this.closeModal} />
        </Modal>
      </Wrapper>
    );

И мой последний потомок, куда я хочу после отправки перерисовать родительский контейнер:

export class Form extends React.Component {

  render() {
    return (
      <article>
        <form
          onSubmit={e => {
            e.preventDefault();
            this.props.submit();
            this.props.close();
            //Somehow re-render parent
          }}
        >
          <div className="row" style={{ textAlign: 'start' }}>
            Do you really want to change status?
            <div className="col-md-12 buttonContainer">
              <ButtonA
                label="Submit"
                style={{ width: '50%' }}
                primary
                type="submit"
              />
            </div>
          </div>
        </form>
      </article>
    );
  }
}

Я попытался перезагрузить страницу с помощью window.location.reload();, и она работает. Но я думаю, что это плохая практика с React. Может быть, кто-то может посоветовать мне, как сделать это лучше?

РЕДАКТИРОВАТЬ: я добавляю родительский редуктор и 4-й дочерний редуктор.

родительский редуктор:

const initialState = fromJS({
  loading: false,
  error: false,
  listData: {
    list: false,
  },
});

function pageReducer(state = initialState, action) {
  switch (action.type) {
    case FETCH_LIST_BEGIN:
      return state
        .set('loading', true)
        .set('error', false)
        .setIn(['listData', 'list'], false);
    case FETCH_LIST_SUCCESS:
      return state
        .setIn(['listData', 'list'], action.list)
        .set('loading', false);
    case FETCH_LIST_FAILURE:
      return state.set('error', action.error).set('loading', false);
    default:
      return state;
  }
}

export default pageReducer;

4-й ребенок редуктор:

const initialState = fromJS({});

function formReducer(state = initialState, action) {
  switch (action.type) {
    case SUBMIT:
      return state;
    default:
      return state;
  }
}

export default formReducer;

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Мы используем Redux или новый Context API React, чтобы избежать проблем с бурением в реакторе. При использовании вы можете отправлять действие из родительского компонента и подключать соответствующий редуктор к вашему ребенку 4-го уровня. Поэтому, когда ваш редуктор обновляет глобальное состояние (хранилище), подключенный компонент будет повторно визуализироваться и принимать обновленное состояние, как в подпорках.

0 голосов
/ 07 сентября 2018

Просто передайте this.props.onCompMount() как реквизиты дочерним компонентам, а затем вызывайте его в дочерних компонентах каждый раз, когда он обновляется.

...