В моей компании мы переносим интерфейсный веб-приложение в ReactJS. Мы работаем с приложением create-response-app (обновлено до версии v16), без Redux. Теперь я застрял на странице, структура которой может быть упрощена следующим изображением:
Данные, отображаемые тремя компонентами (SearchableList, SelectableList и Map), получаются с тем же запросом на бэкэнд в методе componentDidMount()
MainContainer. Результат этого запроса затем сохраняется в состоянии MainContainer и имеет структуру более или менее:
state.allData = {
left: {
data: [ ... ]
},
right: {
data: [ ... ],
pins: [ ... ]
}
}
LeftContainer получает в качестве prop state.allData.left
из MainContainer и передает props.left.data
в SearchableList, еще раз как prop.
RightContainer получает в качестве prop state.allData.right
из MainContainer и передает props.right.data
в SelectableList и props.right.pins
на карту.
SelectableList отображает флажок, чтобы разрешать действия над его элементами. Всякий раз, когда действие происходит над элементом компонента SelectableList, оно может иметь побочные эффекты на выводах Map.
Я решил сохранить в состоянии RightContainer список, содержащий все идентификаторы элементов, отображаемых SelectableList; этот список передается как реквизиты как для SelectableList, так и для Map. Затем я перехожу к SelectableList обратного вызова, что всякий раз, когда делается выбор, обновляется список идентификаторов внутри RightContainer; новые реквизиты поступают как в SelectableList, так и в Map, и поэтому render()
вызывается в обоих компонентах.
Он отлично работает и помогает сохранить все, что может произойти с SelectableList и Map внутри RightContainer, но я спрашиваю, правильно ли это для лифтингового состояния и источника истины.
В качестве возможной альтернативы я подумал о добавлении свойства _selected
к каждому элементу в state.right.data
в MainContainer и передать выбранный обратный вызов на три уровня до SelectableList, обрабатывая все возможные действия в MainContainer. Но как только произойдет событие выбора, это в конечном итоге приведет к загрузке LeftContainer и RightContainer, введя необходимость внедрения логик, таких как shouldComponentUpdate()
, чтобы избежать бесполезного render()
, особенно в LeftContainer.
Что является/может быть лучшим решением для оптимизации этой страницы с точки зрения архитектуры и производительности?
Ниже у вас есть выдержка из моих компонентов, чтобы помочь вам понять ситуацию.
MainContainer.js
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
allData: {}
};
}
componentDidMount() {
fetch( ... )
.then((res) => {
this.setState({
allData: res
});
});
}
render() {
return (
<div className="main-container">
<LeftContainer left={state.allData.left} />
<RightContainer right={state.allData.right} />
</div>
);
}
}
export default MainContainer;
RightContainer.js
class RightContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItems: [ ... ]
};
}
onDataSelection(e) {
const itemId = e.target.id;
// ... handle itemId and selectedItems ...
}
render() {
return (
<div className="main-container">
<SelectableList
data={props.right.data}
onDataSelection={e => this.onDataSelection(e)}
selectedItems={this.state.selectedItems}
/>
<Map
pins={props.right.pins}
selectedItems={this.state.selectedItems}
/>
</div>
);
}
}
export default RightContainer;
Спасибо заранее!