I'm trying provide uuidv4 as key prop in my header list item but it gives me warning and asking unique key as prop

392 Views Asked by At
// This is my routes which I'm trying to map through 
const Header = () => {
  const routes = [
    { id: 1, name: 'Home', link: '/' },
    { id: 2, name: 'Blogs', link: '/blogs' },
    { id: 3, name: 'Contact', link: '/about' }
  ];
//Since providing index as key prop is not good I'm giving uuidv4() as key prop
 {
                routes.map(route =>
                  <li className='mr-8'>
                    <NavLink className='px-2' style={navLinkStyles} key={uuidv4()} to={route.link}>{route.name}</NavLink>
                  </li>
                )
              }

This is what I got as warning in my console:

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

Check the render method of `Header`. See https://reactjs.org/link/warning-keys for more information.
    at li
    at Header (http://localhost:3000/static/js/bundle.js:3874:98)
    at div
    at App
    at Router (http://localhost:3000/static/js/bundle.js:90278:15)
    at BrowserRouter (http://localhost:3000/static/js/bundle.js:89087:5)

Proving index as key prop give same warning and uuidv4() also. What should I give as key prop in this case?

3

There are 3 best solutions below

0
On BEST ANSWER

Your routes have IDs, which look to be unique identifiers for a particular route (link would probably work too), so use that. Don't use uuid (or Math.random) as a key (unless you really have no other way to identify an element being mapped over), and put the key on the element directly returned from the callback.

routes.map(route =>
    <li className='mr-8' key={route.id}>
        <NavLink className='px-2' style={navLinkStyles} to={route.link}>{route.name}</NavLink>
    </li>
)
0
On

It's true, if you really don't have an way to identify an element, you could use an mix strategy between UUID library and

export const getUniqueId = () => {
    return `${uuidv4()}-${generateUniqueStringWithTimestamp()}`;
}

timestamp

export const generateUniqueStringWithTimestamp = () => {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    const hour = String(now.getHours()).padStart(2, '0');
    const minute = String(now.getMinutes()).padStart(2, '0');
    const second = String(now.getSeconds()).padStart(2, '0');
    const miliseconds = String(now.getMilliseconds());
  
    return `${year}${month}${day}${hour}${minute}${second}${miliseconds}`;
}

you will get something like this "4f6fdbc1-2c5d-4e64-a9e1-99878ff68e58-20230512113800865"

Remember that with UUID library you could give duplicates so with this strategy you will decrease the probability of error

Reference: https://www.npmjs.com/package/uuid

enter image description here

0
On

if you don't have a value in the array to use as key, the solution proposed in this answer works like a charm:

...
routes.map(route =>
  <li className='mr-8' key={JSON.stringify(route)}>
...