#reactjs
#reactjs
Вопрос:
Я пытаюсь эффективно создать представление с вкладками, в котором содержимое каждой вкладки извлекается только при нажатии на вкладку. Я реализовал это, используя набор кнопок в качестве заголовков, которые обновляют currentTab
значение в состоянии контейнера, и переключатель, который отображает компонент только на основе этого currentTab
значения. Затем я извлекаю данные из componentDidMount
функции, достигая своего намерения загрузки, когда вкладка фактически выбрана.
Проблема в том, что я не хочу загружать данные каждый раз при выборе вкладки. Только в первый раз. Я хочу, чтобы данные в этих компонентах оставались, когда я нажимаю назад, чтобы их не нужно было извлекать снова. Я уже пытался сохранить ссылки на каждый компонент tab в компоненте контейнера и повторно использовать их, но это не сработало. Это выглядело примерно так:
class MyContainer extends React.Component{
constructor(props){
super(props);
this.state = {activeTab: this.props.initialTab}
this.tabs = {
'Actions': null,
'Drawsheet': null,
'Players': null,
'About': null,
'Contact': null
};
}
getTab(){
const tab = this.state.activeTab;
if(this.tabs[tab] != null){
return this.tabs[tab];
}
else {
let newTab;
switch (tab){
case 'Actions':
newTab = <ActionsTab user={this.props.user}/>;
break;
case 'Drawsheet':
newTab = <DrawsheetTab event={this.props.event}/>;
break;
case 'Players':
newTab = <PlayersTab event={this.props.event}/>;
break;
case 'About':
newTab = <AboutTab event={this.props.event}/>;
break;
case 'Contact':
newTab = <ContactTab event={this.props.event}/>;
break;
}
this.tabs[tab] = newTab;
return newTab;
}
}
render(){
let content = this.getTab();
return(content);
}
Этот подход по-прежнему отлично отображает и все, кроме его перемонтирования каждый раз, когда я визуализирую компонент, вместо сохранения его статуса при сохранении и повторном использовании ссылки на него.
Каков наилучший способ для меня скрыть уже созданные вкладки без их размонтирования? Очевидно, что недостаточно сохранять ссылки, пока они не отображаются, я предполагаю, что мне нужно отобразить их все, но просто использовать display: none
или что-то в этом роде? Однако я читал в других сообщениях, что приведет к его повторному монтированию, и использование visibility
заставит их по-прежнему занимать место, пока они скрыты, что также неприемлемо.
Ответ №1:
В итоге я придумал свое собственное решение, основанное на ответе @Diceros. Публикация для всех, кто натыкается на эту тему.
Я добавил tabData
массив в состояние контейнера, а затем создал saveTabData
функцию, которую я передал каждому компоненту как onLoadData
и передал сами данные компоненту.
В каждом компоненте tab вместо вызова this.setState
для сохранения данных из выборки я вызываю обратный this.props.onLoadData
вызов для сохранения данных в массив containers tabData
. Затем я переработал методы рендеринга каждого компонента, чтобы получать данные из this.props
вместо this.state
и просто отображать «Загрузка …», когда данные реквизита равны нулю (т. Е. когда он еще не загружен).
Ответ №2:
Во-первых, я бы переместил весь переключатель с компонентами вкладок в рендеринг, а затем я бы использовал componentDidUpdate
и проверил, была ли изменена активная вкладка, и если да, сохраните новую вкладку в какой-то коллекции в состоянии (ниже я использовал opennedTabs
), где вы будете собирать всеиз ранее открытых вкладок, и если вкладка еще не была открыта, извлеките данные. Если он был ранее открыт, не извлекайте данные снова. Используя этот способ, вам не нужно заботиться о рендеринге и размонтировании вкладок и просто правильно обрабатывать данные.
В коде:
componentDidUpdate() {
let opennedTabs = [...this.state.opennedTabs];
if (prevState.activeTab !== this.state.activeTab) {
if (opennedTabs?.length > 0 amp;amp; !opennedTabs.includes(this.state.activeTab)) {
//Fetch the data for this.state.activeTab
opennedTabs.push(activeTab);
this.setState({ opennedTabs });
}
}
}
render() {
switch (this.state.activeTab){
case 'Actions':
return <ActionsTab fetchedData={dataActionsTab} user={this.props.user}/>;
case 'Drawsheet':
return <DrawsheetTab fetchedData={dataDrawsheetTab} event={this.props.event}/>;
case 'Players':
return <PlayersTab fetchedData={dataPlayersTab} event={this.props.event}/>;
case 'About':
return <AboutTab fetchedData={dataAboutTab} event={this.props.event}/>;
case 'Contact':
return <ContactTab fetchedData={dataContactTab} event={this.props.event}/>;
}
Комментарии:
1.
opennedTabs.push(activeTab);
Откуда берется эта переменная activeTab? Это должен быть сам компонент или строковый ключ? Если компонент, где я должен его хранить и устанавливать?2. activeTab следует использовать для хранения уникального идентификатора текущей вкладки / вкладки по умолчанию. Позже это можно использовать, чтобы проверить, открыта ли вкладка или нет. В основном я понимаю это из вашего примера.