5

I was just wondering while reading article from https://coderwall.com/p/jdybeq/the-importance-of-component-keys-in-react-js.

It has a simple fiddle code which says - If you dont have unique constant keys you might end up in

  1. Recreating the DOM node of a component when the key is not constant
  2. Reusing a DOM node to render another component when the key is not unique

Its quite confusing in below cased -

  1. Why I give key = index (even though its unique and constant why react behaves weirdly?)
  2. What exactly happens when the keys are unique but not constant (Does it check if key exist in DOM if not just remove it.)
Display Name
  • 337
  • 5
  • 13
  • It's *not* a good idea to use index as key, since they are not really constant -- if you delete an item, all items that follow it will change index. – Aaron Beall Aug 11 '16 at 21:07

2 Answers2

17

Expanding on the @Deadfish answer. Let's say you have 10 todo items, and each item has state (e.g. whether it is in editing mode).

On the next render pass, there are only 9 todo items left. E.g. because you deleted one of the items.

Now react needs to know which of the original 10 items are still left, so it can preserve the state of each item, and re-render only items that changed state.

That is what react uses the key for. If you use the index as the key, then the original keys were 0..9. And the new keys are 0..8.

This can cause several problems:

  1. React will ALWAYS conclude that you deleted the last item in the list, which is not necessarily correct. There are other posts on SO about this, e.g this one
  2. React will ALWAYS conclude that the items did not change order, so react will think that any state of original item no 5 will still be state of item no 5. But if you deleted eg. item no. 3, then all items should have moved up in the list. which is what the other answer pointed out.
  3. If the items in the list do not have any state (only props) - e.g. the title of your todo - then your rendering will become very inefficient. If you delete the first item, then react will conclude that ALL items now have a new text, and will re-render ALL remaining items (instead of efficiently deleting just the first item from the DOM).

Using unique and constant keys - so not just unique in a single render run, but especially constant over multiple render-cycles - will ensure that everything works as intended, and will ensure react updates DOM efficiently.

Community
  • 1
  • 1
wintvelt
  • 13,855
  • 3
  • 38
  • 43
  • Amazing insights. Thank you so much – Display Name Aug 12 '16 at 05:41
  • @wintvelt: I m novice to React. As I am able to understand theoretically. but I m not getting any error with code using a key as an array index, though deleting the element in an array. So Can you please help me to get a clear idea? – albert Jegani Dec 28 '16 at 15:28
  • @wintvelt: How to see the performance issue(re-render ALL remaining items) in debugging or is it any chance to see the performance issue in debugging? – albert Jegani Dec 28 '16 at 15:45
  • It is not really expected that you will get an error if you use the index as the key. What react uses the key for, is to find out which of the items in render 2 are the same items an in render 1 before. So react can find out which item was deleted for example. What typically happens if you use the index as the key, is that when you delete item 5 of a list of 10, that react deletes the wrong one, item no 10 instead of 5. Not always. Depends on the rest of your code, but it may happen. And you will not get an error. – wintvelt Dec 28 '16 at 20:25
  • On the performance issue: if you use index as the key, and you reorder, it may happen that react will re-render the entire list, instead of doing a smart reorder. I haven't tested this myself, but I suspect that with reordering long lists, this will be slower. – wintvelt Dec 28 '16 at 20:28
  • @wintveltWhy will react conclude that all items now have a new text. 'If the items in the list do not have any state (only props) - e.g. the title of your todo - then your rendering will become very inefficient. If you delete the first item, then react will conclude that ALL items now have a new text, and will re-render ALL remaining items (instead of efficiently deleting just the first item from the DOM).' – Suraj Jain Mar 26 '19 at 05:55
  • @SurajJain Because react tries to be efficient in rendering lists. If your list has key, value (props) of eg 1: Apples, 2: Bananas, 3: Coconuts, and you delete the first item with index as key, your new list is: 1: Bananas, 2: Coconuts, then react will re-render all items again, because the value (prop) of each item changed. If your key, values would be Apples: Apples, Bananas: Bananas, Coconuts: Coconuts, react can (probably) deduce from the competing keys between new list (Bananas; Bananas, Coconuts: Coconuts) that the first item was deleted, and do a more efficient update of the list. – wintvelt Mar 26 '19 at 23:03
5

It is always good to have react keys constant and unique. There will be times when index will not work well.

Let us consider a scenario where we have two components TodoList and TodoItem in our application. The TodoList component iterates over a todos array and renders TodoItem for each todo. Let's say you have opened the second TodoItem for editing. So it's state says {editing: true} and it renders an input box instead of Label.

Now if you have used index as key, then upon deleting the second todo, the third todo will inherit state from the deleted todo and display an input box instead of Label. This happens since they both share same key.

I hope I made myself clear.

Deadfish
  • 2,047
  • 16
  • 17