У меня есть родительский компонент приложения, который отображает маршрут с помощью компонента отчета. Компонент 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));





ComponentDidUpdate () будет вызываться всякий раз, когда обновляются свойства дочернего компонента.
В этом сценарии происходит следующий поток:
reports = {this.state.reports} передается дочернему компонентуreports изменилась.updateReports(newState) в родительском компоненте.reports = {this.state.reports} передается ДочернемуИспользование ComponentDidMount () в этом сценарии должно устранить проблему, но, что более важно с точки зрения архитектуры решения, ваш вызов службы должен быть извлечен в отдельный файл и вызван из родительского, что сделает дочерний компонент немым.
Я могу многое сказать, но я здесь, чтобы прояснить, почему возникает цикл: P
Все зависит от частоты, с которой вам нужно обновлять эти отчеты ... ComponentDidMount() вашего родителя - лучшее место, чтобы сделать вызов только один раз, а затем просто передать его своему ребенку и убрать все функции, в качестве альтернативы этот метод в child в большинстве случаев вызывается только один раз. Вы также можете выполнять сервисные вызовы на constructor(), но обычно это не лучшая практика.
что, если я хочу вызвать только тогда, когда загружен дочерний маршрут? Как лучше всего с этим справиться?