JSX is merely JavaScript and to render a list you can use the array method .map
to map an array to React elements. However, if you don't use the key
prop correctly, it can lead to unexpected results, so we explore what can happen and how to use the key
prop correctly.
Instructor: [00:00] Here, we have an app component with an all-items property. We're going to render those out with app.all-items.map, with item. Inside of here, we'll render a div with item.value, and close off that div. We get apple, orange, grape, and pear.
[00:21] If we open up the developer tools, we're going to get this warning from React, saying each child in an array or iterator should have a unique key prop.
[00:30] The problem is that what this expression evaluates to is an array. As we re-render and re-render, React needs to be able to check the old array from the new array, to know which items are removed, which items are added to. To do this, it needs to keep track using a key.
[00:48] For this key, we need to keep it as something totally unique to that item. Lucky us, that's the ID. We can say item.ID, and we're not getting that warning anymore. Now, as things are added and removed as state changes, React can keep track of these nodes.
[01:05] It doesn't actually really matter all that much in this scenario. We're going to add a little bit of code here to demonstrate a scenario where it really does matter.
[01:14] What I added was some state to keep track of some items, because we're going to make that dynamic. We can now add and remove items from that state, and then we render the items based on that state.
[01:25] We have this add button, where we can click to add items, and then we render all the items that are in the state, with a button to remove them and what the value of that item is, and then this input to demonstrate the real problem here.
[01:38] We're going to go ahead and click add. We're going to get that warning, because we don't have a key prop. I'll just add all of the items we have available.
[01:45] Let's go ahead, and I'm going to say 1, 2, 3, and 4. Let's say I want to get rid of the pear, 4. That works great. Now, let's say I want to get rid of orange. That has 2 in it, and I click minus next to the orange. The grape now actually has 2, when it had 3 before. If I do the same here to apple, now I have grape, and that has 1. Things are really messed up.
[02:15] The reason is that this input is not actually associated to these items directly, because we haven't shown React how to keep track of these items and the associated elements. That's why we need to have a key here, so that React can keep track of the elements that are associated with our data.
[02:35] Here, we could try to do an index. Sometimes, that'll work OK, but in our scenario, that won't work. If we have 1, and 2, and 3, and we'll remove one, now things are all kinds of messed up.
[02:50] Sometimes, you'll be forced to use an index. You don't have anything else that's unique. Sometimes, if you just have an array of strings, then you can use the identity of that item itself. In our case, we're lucky, because we have an ID. That's normally what you want to do, is have your data have an ID, a unique identifier.
[03:08] Now, if we add all these, we can say 1, 2, 3, and 4. If we remove 2, then that's going to actually remove 2. We remove 4, we remove 1, and we're left with grape is 3. There's one other scenario where not using a key properly can cause real problems, and that's with element focus.
[03:27] I wrote this demo here for you. Every second, these items are being randomized and then re-rendered. This is an example of not using a key at all. We can see that's being rendered right here, with just an input for each item. If we use the key as the index, with the input for each item, and then we use a proper key, with a unique identifier for each item.
[03:50] If I click in here, you'll notice my focus is staying in the same input. It's not following the item that it should be. If I highlight the text, every single time it's updated, that isn't going to get un-highlighted.
[04:03] We actually have the exact same problem when we use key as an index, because it's not a proper identifier. Only when we use the key properly will our focus be taken to the right place, keeping track with the input that is associated with the item that we are rendering.
[04:18] Even if I select all the text, or if I move anywhere in that input, React will make sure that the user's focus and their selection remains in the right place, because we have the key properly set.