Skip to content
Advertisement

How to pass key to a cloned component in react using React.cloneElement()

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

Advertisement