3

Imagine we have this JSX:

<App>
  <Counter value={this.state.counter1} />
  <Counter value={this.state.counter2} />
</App>

And we also have this (imagine this.state.counters is an array of values):

<App>
  { this.state.counters.map((value, i) => <Counter value={value} key={i} /> )}
</App>
  1. Why do we need to set a key in the second example for each Counter and not in the first example? Isn't it rendering basically the same?
  2. Which of both approaches do you think is better in terms of performance, having all counter values in an array or using a key for each one?
Emi
  • 4,597
  • 2
  • 31
  • 34

1 Answers1

4

Why do we need to set a key in the second example for each Counter and not in the first example? Isn't it rendering basically the same?

Yes, the result is the same.

In the first case React already knows the order of the components because you have defined it as such in your code.

In the second case the order of the components depends entirely on how your array is defined. React cannot know this just by knowing which array to iterate. If the array is ever altered (items removed, added or mutated), how should React know if a Component should be updated with new props or simply change their order?

Consider this example:

const arr = [{id: 1, name: 'Chris'}, {id: 2, name: 'Emi'}];

<App>
  {arr.map(x => <Component name={x.name} id={x.id} />)}
</App>

This will yield the same result as:

<App>
  <Component id={1} name="Chris" />
  <Component id={2} name="Emi" />
</App>

However, what happens if we change the array to:

const arr = [{id: 1, name: 'Emi'}, {id: 2, name: 'Chris'}];

Did we rename Chris to Emi and Emi to Chris or did they only swap places? React has no way of knowing this "automatically".

For this reason, we define a key prop which tells React how your data is modelled. Had we defined our key here to be name React will interpret it as a placement swap. Had it been id, React would update the props.

Bonus case: If we defined our key to be id, and we changed {id: 1, name: 'Chris'} to {id: 3, name: 'Chris'} the corresponding Component would be unmounted and replaced with a new one (and not a prop update!). Why? Because the Component with identity 1 exists no longer.

For more info about keys: Understanding unique keys for array children in React.js


Which of both approaches do you think is better in terms of performance, having all counter values in an array or using a key for each one?

I think any performance differences is negligible here. The "right" way is more down to preference and what makes sense to you as a programmer. Typically, for readability, if you want to repeatedly render the same component but with different props, map an array. Also, if you have many Components, it makes more sense to keep them in an array.

Chris
  • 57,622
  • 19
  • 111
  • 137
  • Nice explanation! This is another "issue" when using arrays. Yo should avoid using the index as the key to avoid unwanted behavior, so you should create an "id" for each entry or use an object with key/values instead of an array. Am I right? I'm wondering when using an array is a good idea, but I guess I should open another question for this! – Emi Jun 28 '18 at 11:21
  • 1
    @Emi check out the link in my answer. It should answer your question. But basically, it depends. If you don't change your array (like re-order, add/remove, etc) then using the index is perfectly fine. It is also fine if you add items but always only at the end of the array or if you remove items but always only the last item. Again, read the link above. – Chris Jun 28 '18 at 11:33