I have implemented Material UI’s tabs successfully by hard-coding the content, but when I tried to make a my hard coded tabs with a .map function to populate the content from a data source (simple json), it no longer works. Can anyone see why? The only change I made was to the MyTabs component below where there are now two .map functions instead of hard coded tabs.
Many thanks for your help!
Here is my data:
export const TabsData = [ { tabTitle: 'Tab 1', tabContent: 'Hello 1', }, { tabTitle: 'Tab 2', tabContent: 'Hello 2', }, { tabTitle: 'Tab 3', tabContent: 'Hello 3', }, ];
Here is my MyTabs component:
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;
And here is the TabsPanel component:
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 && <Box className={classes.contentContainer}>{children}</Box>} </div> ); } TabContentPanel.propTypes = { children: PropTypes.node, index: PropTypes.any.isRequired, value: PropTypes.any.isRequired, }; export default TabContentPanel;
Advertisement
Answer
It doesn’t work because you added some extra Fragment
s (<>
and </>
) in the Tabs
component and the Tabs
component doesn’t accept a Fragment
as a child:
If you remove those, it will work as expected:
{TabsData.map((tabInfo, index) => ( <Tab label={tabInfo.tabTitle} id={`simple-tab-${index}`} key={tabInfo.tabTitle} ariaControls={`simple-tabpanel-${index}`} /> ))}
And please use the key
prop with a unique id if you create an array of elements. Each child in a list should have a unique “key” prop.