Почему вкладки пользовательского интерфейса Material перестают работать, когда я использую .map для динамического заполнения содержимого вместо жесткого кодирования?

#reactjs #material-ui #state #array.prototype.map

#javascript #reactjs #material-ui #состояние #array.prototype.map

Вопрос:

Я успешно реализовал вкладки Material UI путем жесткого кодирования содержимого, но когда я попытался создать свои жестко закодированные вкладки с помощью функции .map для заполнения содержимого из источника данных (простой json), он больше не работает. Кто-нибудь может понять, почему? Единственное изменение, которое я внес, было в компонент MyTabs ниже, где теперь есть две функции .map вместо жестко закодированных вкладок.

Большое спасибо за вашу помощь!

Вот мои данные:

 export const TabsData = [
  {
    tabTitle: 'Tab 1',
    tabContent: 'Hello 1',
  },
  {
    tabTitle: 'Tab 2',
    tabContent: 'Hello 2',
  },
  {
    tabTitle: 'Tab 3',
    tabContent: 'Hello 3',
  },
];
 

Вот мой компонент MyTabs:

 import React, { useState } from 'react';

// Material UI
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';

// Data
import { TabsData } from '../../page-templates/full-page-with-tabs/FullPageWithTabsData';

//Components
import TabContentPanel from '../tabs/tab-content-panel/TabContentPanel';

const MyTabs = () => {
  const classes = useStyles();
  const initialTabIndex = 0;
  const [value, setValue] = useState(initialTabIndex);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };
  return (
    <>
     <Tabs
       value={value}
       onChange={handleChange}
       aria-label=""
       className={classes.tabHeight}
       classes={{ indicator: classes.indicator }}
     >
      {TabsData.map((tabInfo, index) => (
        <>
         <Tab
            label={tabInfo.tabTitle}
            id={`simple-tab-${index}`}
            ariaControls={`simple-tabpanel-${index}`}
         />
        </>
       ))}
    </Tabs>
    {TabsData.map((tabInfo, index) => (
        <TabContentPanel value={value} index={index}>
           {tabInfo.tabContent}
        </TabContentPanel>
    ))}
    </>
  );
};

export default MyTabs;
 

А вот и компонент TabsPanel:

 import React from 'react';
import PropTypes from 'prop-types';

// Material UI
import { Box } from '@material-ui/core';

function TabContentPanel(props) {
  const { children, value, index, ...other } = props;
  const classes = useStyles();
  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
      {...other}
    >
      {value === index amp;amp; <Box className={classes.contentContainer}>{children}</Box>}
    </div>
  );
}

TabContentPanel.propTypes = {
  children: PropTypes.node,
  index: PropTypes.any.isRequired,
  value: PropTypes.any.isRequired,
};

export default TabContentPanel;
 

Ответ №1:

Это не работает, потому что вы добавили дополнительные Fragment s ( <> и </> ) в Tabs компонент, а Tabs компонент не принимает a Fragment как дочерний элемент:

Если вы удалите их, все будет работать так, как ожидалось:

 {TabsData.map((tabInfo, index) => (
  <Tab
    label={tabInfo.tabTitle}
    id={`simple-tab-${index}`}
    key={tabInfo.tabTitle}
    ariaControls={`simple-tabpanel-${index}`}
  />
))}
 

И, пожалуйста, используйте key prop с уникальным идентификатором, если вы создаете массив элементов. У каждого дочернего элемента в списке должен быть уникальный «ключевой» реквизит.

Комментарии:

1. У-у-у! Теперь это работает отлично! Большое вам спасибо за вашу помощь и за дополнительные советы по включению ключа. Очень признателен и избавил меня от траты времени на попытки разобраться в этом! 🙂