I have a tabs component that accepts the elements array as props and I am trying to assign key to cloned elements by using React.cloneElement() with no luck. I am passing down elements as an array. Mapping over that elements array, cloning each component in that array and trying to assign key to each element.But, I still keep getting the warning about each component should have a key prop. How can I assign keys to each component by using React.cloneElement()?
Below is my elements array that I am passing to my Tabs component.
Below is my tabs component:
import React, {useState, useEffect, useCallback} from 'react'; import classes from './tabs.module.css'; const Tabs = ({ tabsData, active = 0 }) => { const [activeTab, setActiveTab] = useState(active); const setActiveTabIndex = useCallback((index) => { setActiveTab(index) }, [activeTab]) return ( <div className={classes.tabsContainer}> <ul className={classes.tabsList}> { tabsData.map((item, index) => ( <li className={`${classes.tab} ${index === activeTab && classes.activeTab}`} onClick={() => setActiveTabIndex(index)}>{ item.tabTitle }</li> ))} </ul> <div className={classes.textContainer}> {tabsData[activeTab].content.map((ElementItem, index) => ( React.cloneElement(ElementItem, {key:index}) ))} </div> </div> ) } export default Tabs
Below is the array that I am passing down to that tabs component.
const tabsData = [ { tabTitle: "Description", content: [<h1 className={classes.tabTitle}>{'Product Description'}</h1>, productDetails.shortDescription.html ? <RichContent html={productDetails.shortDescription.html} /> : <RichContent html={"<p>No short description found</p>"} />] }, { tabTitle: "Attributes", content: [<h1 className={classes.tabTitle}>{'Product Attributes'}</h1>, <CustomAttributes customAttributes={customAttributesDetails.list} />] } ]
I have also tried the following to try to assign key to each element.
<React.Fragment key={index}> { React.cloneElement(ElementItem) } </React.Fragment>
Advertisement
Answer
Problem is in this part of the code
<ul className={classes.tabsList}> {tabsData.map((item, index) => ( <li key={index} className={`${classes.tab} ${index === activeTab && classes.activeTab}`} onClick={() => setActiveTabIndex(index)}>{ item.tabTitle }</li> ))} </ul>
You should also add key
prop to each li
element