Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the cause of the Warning: Each child in a list should have a unique "key" prop

I often run into the error

Warning: Each child in a list should have a unique "key" prop.  Check the render method of `MyComponent`.

in React. The error message always tells you the offending component, but not the specific HTML tag / virtual DOM element that is offending. Working in a large code base with sometimes big components, this makes finding the source of the error very difficult.

What causes this error? I'm looking for a definitive list.

  • A tag in an array with a "key" prop missing entirely (pretty sure)
  • Two tags in an array with the same "key" prop value? (i thought there was a different error message for this)

Do two elements written side-by-side (such as <div></div><div></div>) count as "children in a list"? Will they also cause the error?

What are effective strategies for finding the offensive tag?

  • adding key={Math.random()} to every single keyless tag in the component, one-by-one, until the error disappears, and then seeing which one you added last. (can be time consuming, and sometimes doesn't work)
  • undoing changes chronologically until the error disappears. (can be time consuming)
  • something better here

I am looking for a thorough and canonical answer.

like image 618
mareoraft Avatar asked Jan 24 '20 20:01

mareoraft


2 Answers

You can find offending part by looking for map calls in your jsx. Each top-level element inside map should have key property, i.e.

{items.map(item => (
  <div key={item.id}>
    <div>{item.name}</div>
    <div>{item.description}</div>
  </div>
))}

Docs have some explanations on the subject, in particular:

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys

When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort

We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state.

UPD

If you want to use Math.random, I think the better solution might be using UUIDv4. For example, this package can generate them. While theoretically it is possible to generate two similar UUIDs, chance is very low and you need to generate a lot in seconds (some numbers). However, I never did that and can't say how much using UUID as key impacts performance. Given what documentation says about keys, I guess react will always think that all elements were removed and new ones added.

So the best solution is to have some id associated with each item. If you render an array of unique strings, item itself can be the key. If items in array do not have any unique id and order of items is never changed and items can not be removed from array, using index should be a safe option. And as last resort you can try uuid.

UPD2

As regards to finding offensive code, I noticed that there is a trace in this warning, looking like this:

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

Check the render method of `Log`. See https://*b.me/react-warning-keys for more information.
    in div (at Log.js:241)
    in Log (created by ConnectFunction)
    in ConnectFunction (at HomePage.js:10)
    in WithWorkspace (created by ConnectFunction)
    in ConnectFunction (at HomePage.js:8)
    in HomePage (at App.js:24)
    in Route (at AuthenticatedRoute.js:14)
    in AuthenticatedRoute (created by ConnectFunction)
    in ConnectFunction (at App.js:23)
    in Switch (at App.js:22)
    in div (at App.js:21)
    in div (at App.js:18)
    in Unknown (created by ConnectFunction)
    in ConnectFunction (at FetchAll.js:165)
    in Unknown (created by ConnectFunction)
    in ConnectFunction (at FetchAll.js:164)
    in Unknown (created by ConnectFunction)
    in ConnectFunction (at FetchAll.js:163)
    in FetchAll (at App.js:17)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:15)
    in App (at src/index.js:14)
    in Provider (at src/index.js:13)

Here offending file is named Log.js, line 241. I don't know if trace is always present and correct but it might help.

As for me, I check result in browser very often and console usually is open, so when I see that warning, I usually know what I did with arrays just recently and where I forgot the key.

like image 200
Gennady Dogaev Avatar answered Nov 15 '22 23:11

Gennady Dogaev


Here is a partial answer based on what I've learned so far.

What does/doesn't cause this error? Here is a list:

  1. A tag in an array with a "key" prop missing causes the error. For example,

    <Fragment>
        {[
            <div>one</div>
        ]}
    </Fragment>
    

gives the error, regardless of the number of children.

  1. A tag not in an array with a "key" prop missing does not cause the error. For example,

    <Fragment>
        <div>one</div>
    </Fragment>```
    

does not give the error, regardless of the number of children.

  1. A tag in an array with a "key" prop present with a value of undefined causes the error. For example,

    <Fragment>
        {[
            <div key={undefined}>one</div>
        ]}
    </Fragment>```
    

gives the error, even though the key prop is typed out. It's important to be aware of this, because it means that you could assign a variable to the key prop and still run into this error. For example, you might have bad data coming into your application so that key={myobj.id} triggers the error because myobj.id is undefined.

  1. A tag in an array with a "key" prop present with duplicate defined values does not cause the error. For example,

    <Fragment>
        {[
            <div key={'chicken'}>one</div>,
            <div key={'chicken'}>one</div>
        ]}
    </Fragment>```
    

does not give the error, even though the keys are not unique!

What causes this error? In summary:

The error is caused exactly when there exists an Array containing an item that is a tag which has no key prop assigned or has a key prop with an assigned value of undefined.

like image 22
mareoraft Avatar answered Nov 15 '22 22:11

mareoraft