Бесконечный цикл с React comonentDidUpdate

У меня есть родительский компонент приложения, который отображает маршрут с помощью компонента отчета. Компонент App выполняет вызов ajax в своем методе componentDidMount, а Report также выполняет некоторые вызовы ajax в своем методе componentDidUpdate, после чего вызывает родительский метод updateReports. Приложение застревает в бесконечном цикле, в котором потомок снова и снова выполняет свои вызовы ajax.

Приложение

...
  updateReports(report) {
    console.info('updateReports', report)
    if (report.submittal) {
      this.setState({ reports: { submittal: report.submittal } });
      if (report.specification) {
        this.setState({ reports: { specification: report.specification } });
      }
    }
  }
...    
  componentDidMount() {
    console.info('environment', process.env);
    console.info('App state', this.state);
    if (!this.state.projectName) {
      const err = new Error('Project Name must be supplied in the url: /<projectName>');
      return this.handleError(err);
    }

    this.populateProjectId();
  }

  populateProjectId() {
    return Api.getProjectId(process.env.REACT_APP_API_PATH, this.state.projectName)
      .then((projectId) => {
        console.info('App adding projectId to state', projectId);
        this.setState({ projectId });
      })
      .catch((err) => {
        console.info(err);
        this.handleError(err);
      });
  }
...
  render() {
const commonProps = {
  query: this.state.query,
  projectName: this.state.projectName,
  projectId: this.state.projectId
};
...
            <Route
              path = "/:projectName/admin"
              render = {(props) => (
                <Admin
                  {...{ ...commonProps }} reports = {this.state.reports}
                  updateReports = {this.updateReports}
                  handleError = {this.handleError}
                />
              )}
            />

Админ

...
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.info('Admin componentDidUpdate')
    const { projectId } = this.props;

    const apiPath = process.env.REACT_APP_API_PATH;
    Api.fetchReport(apiPath, projectId, 'submittal', null)
      .then((res) => {
        console.info('submittal report result', res);
        return res;
      })
      .then((submittal) => {
        Api.fetchReport(apiPath, projectId, 'specification', null).then((res) => {
          console.info('specification report result', res);
          const newState = { submittal, specification: res };
          console.info('Calling updateReports', newState);
          this.props.updateReports(newState);
        });
      })
      .catch((err) => {
        console.info(err);
        this.handleError(err);
      });
  }

  render() {
    return (
      <div>
        <Report reports = {this.props.reports} />
      </div>
    );
  }
}

export default withRouter(withStyles(styles)(Admin));
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
131
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ComponentDidUpdate () будет вызываться всякий раз, когда обновляются свойства дочернего компонента.

В этом сценарии происходит следующий поток:

  1. reports = {this.state.reports} передается дочернему компоненту
  2. Затем дочерний элемент обновляется, потому что его опора reports изменилась.
  3. ComponentDidUpdate () вызывается, а затем запускает updateReports(newState) в родительском компоненте.
  4. В родительском компоненте состояние обновляется новыми отчетами
  5. Обновленный reports = {this.state.reports} передается Дочернему
  6. Повторить 2-5

Использование ComponentDidMount () в этом сценарии должно устранить проблему, но, что более важно с точки зрения архитектуры решения, ваш вызов службы должен быть извлечен в отдельный файл и вызван из родительского, что сделает дочерний компонент немым.

Я могу многое сказать, но я здесь, чтобы прояснить, почему возникает цикл: P

что, если я хочу вызвать только тогда, когда загружен дочерний маршрут? Как лучше всего с этим справиться?

user994165 19.09.2018 04:36

Все зависит от частоты, с которой вам нужно обновлять эти отчеты ... ComponentDidMount() вашего родителя - лучшее место, чтобы сделать вызов только один раз, а затем просто передать его своему ребенку и убрать все функции, в качестве альтернативы этот метод в child в большинстве случаев вызывается только один раз. Вы также можете выполнять сервисные вызовы на constructor(), но обычно это не лучшая практика.

Tom Rowe 19.09.2018 05:18

Другие вопросы по теме