0

I am mapping an array of objects I imported from a different component but I get the error

Warning: Each child in a list should have a unique "key" prop.

with the following error details

Check the top-level render call using . See https://reactjs.org/link/warning-keys for more information. at li at Heading2 at div at div at Home (webpack-internal:///./pages/index.jsx:27:17) at Layout (webpack-internal:///./components/Layout.jsx:16:19) at $29383e587d62412a$export$9f8ac96af4b1b2ae (/home/kimmoramicky/Desktop/fts_portfolio/node_modules/@react-aria/ssr/dist/main.js:42:28) at MyApp (webpack-internal:///./pages/_app.tsx:28:18) at StyleRegistry (/home/kimmoramicky/Desktop/fts_portfolio/node_modules/styled-jsx/dist/index/index.js:671:34) at AppContainer (/home/kimmoramicky/Desktop/fts_portfolio/node_modules/next/dist/server/render.js:404:29) at AppContainerWithIsomorphicFiberStructure (/home/kimmoramicky/Desktop/fts_portfolio/node_modules/next/dist/server/render.js:433:57) at div at Body (/home/kimmoramicky/Desktop/fts_portfolio/node_modules/next/dist/server/render.js:690:21)

Following is the component containing the array Menu.jsx

export const mainDetails = [
    {
        heading: 'CUSTOM SOFTWARE DEVELOPMENT',
        list: ['- Solutions tailored to specitic business needs', '- Domain experience', '- Technical excellence', '- Process visibility', '- Constraint management framework', '- Non-functional requirements match']
      },
      {
        heading: 'DEVELOPMENT TEAM AUGMENTATION',
        list: ['- Solutions tailored to specitic business needs', '- Domain experience', '- Technical excellence', '- Process visibility', '- Constraint management framework', '- Non-functional requirements match']
      },
      {
        heading: 'IT CONSULTING AND DIGITAL ADVISORY',
        list: ['- Solutions tailored to specitic business needs', '- Domain experience', '- Technical excellence', '- Process visibility', '- Constraint management framework', '- Non-functional requirements match']
      },
      {
        heading: 'SOFTWARE RE-ENGINEERING AND SUPPORT',
        list: ['- Solutions tailored to specitic business needs', '- Domain experience', '- Technical excellence', '- Process visibility', '- Constraint management framework', '- Non-functional requirements match']
      }
]

Following is the component containing the mapping of the array Heading.jsx

import React from 'react'
import Link from 'next/link'
import {mainDetails} from './Menus'

const Heading2 = () => {
  return (
    <main>
      {mainDetails.map(detail => (
        <div className="card">  
          <div className='done'>
            <div>
              <h5 className='font-normal pl-8 text-[#E54416] pb-4 text-lg'>{detail.heading}</h5>
              <ul>{detail.list.map(listItems=>(
                <li>{listItems}</li>
              ))}
              </ul>
            </div>
          </div>
      </div>
      ))}
      
      
    </main>
  )
}

export default Heading2

Also, when I add the key prop to the list like this <ul>{detail.list.map(listItems, i =>(<li key={i}>{listItems}</li>))}, I get a new error saying listItems is undefined

  • `./Menus` won't import `Menu.jsx` - Also give `
    ` a unique key prop. Read more about it https://reactjs.org/docs/lists-and-keys.html#keys
    – evolutionxbox Aug 24 '22 at 08:27
  • When you return JSX from the .map callback, the root element must have the key. Fixed version: https://codesandbox.io/s/vigorous-jones-o12njm?file=/src/Heading2.jsx –  Aug 24 '22 at 08:31

1 Answers1

1

First of all never use an array index to provide a key to your list:

The issue with using key={index} happens whenever the list is modified. React doesn't understand which item was added/removed/reordered since index is given on each render based on the order of the items in the array. Although, usually it's rendered fine, there are still situations when it fails.

See this SO question for more explanation.

That said, you need a unique key for the the first map mainDetails.map() and the heading seems to be a good choice. You also need an unique key for the detail.list.map(), you can create one by merging the heading and the listItems value together like detail.heading + listItems:

    <main>
      {mainDetails.map(detail => (
        <div key={detail.heading} className="card">  
          <div className='done'>
            <div>
              <h5 className='font-normal pl-8 text-[#E54416] pb-4 text-lg'>{detail.heading}</h5>
              <ul>{detail.list.map(listItems=>(
                <li key={detail.heading + listItems}>{listItems}</li>
              ))}
              </ul>
            </div>
          </div>
      </div>
      ))}      
    </main>
johannchopin
  • 13,720
  • 10
  • 55
  • 101