Допустим, у меня есть вложенная структура URI, что-то вроде следующего:
http://example.com/collections/{id}
http://example.com/collections/{collectionId}/categories/{id}
http://example.com/collections/{collectionId}/categories/{categoryId}/book/{id}
Я могу использовать react-router
для визуализации правильного компонента при загрузке страницы и при изменении URI.
Давайте рассмотрим первый случай:
http://example.com/collections/{id}
Предположим, у нас есть компонент CollectionShow
.
Когда компонент загружается впервые, я могу извлечь идентификатор коллекции из URI и загрузить правильную коллекцию:
componentDidMount () {
this.loadCollection(this.props.match.params.id);
}
(Предположим, что loadCollection
загружает коллекцию вызовом AJAX и устанавливает ее в состояние компонента.)
Однако, когда изменяется URI (например, пользователь нажимает на<Link>
, react-router
не полностью перестраивает компонент, он просто обновляет его реквизиты, заставляя его перерисовываться, поэтому для обновления состояния компонента нам также необходимо обновить состояние при обновлении:
componentDidUpdate(prevProps) {
if (!this.state.collection || this.collectionDidChange(prevProps)) {
this.loadCollection(this.props.match.params.id);
}
}
collectionDidChange(prevProps) {
return String(prevProps.match.params.id) !== String(this.props.match.params.id)
}
Пока все хорошо. А как насчет второго URL?
http://example.com/collections/{collectionId}/categories/{id}
Давайте предположим, что у нас есть компонент CategoryShow
.
Теперь нам нужно учитывать не только изменение collectionId
, но и идентификатор категории.Мы должны перезагрузить коллекцию, если этот идентификатор изменится, и мы также должны перезагрузить категорию, если , что изменится.
Проблема связана с вложенностью третьего уровня (компонент BookShow
).В итоге получается что-то вроде этого:
componentDidUpdate(prevProps) {
if (!this.state.collection || this.collectionDidChange(prevProps)) {
this.loadCollection(this.props.match.params.collectionId);
}
if (!this.state.category || this.collectionDidChange(prevProps) || this.categoryDidChange(prevProps)) {
this.loadCollection(this.props.match.params.collectionId)
.then(() => this.loadCategory(this.props.match.params.categoryId);
}
if (!this.state.book || this.collectionDidChange(prevProps) || this.categoryDidChange(prevProps) || this.bookDidChange(prevProps)) {
this.loadCollection(this.props.match.params.collectionId)
.then(() => this.loadCategory(this.props.match.params.categoryId)
.then(() => this.loadBook(this.props.match.params.id);
}
}
Это не только громоздко, но и приводит к значительному дублированию кода во всех трех компонентах: CollectionShow
, CategoryShow
и BookShow
.
Использование приставки не сильно поможет, потому что нам все еще нужно обновлять глобальное состояние при изменении URI.
Существует ли чистый, эффективный и удобный для реагирования способ обработки обновленийвложенные ресурсы, подобные этим?