0

React requires that you have a unique key attribute on elements in an array. The React docs recommend using an id from your data. If you don't have an id then you can use the array index as a "last resort", with the caveat that using an index can cause performance issues when the items can be re-ordered. I've also had some annoying issues when building an array of elements from multiple source arrays and multiple calls to .map(), each with different transformations, in which case the array indexes won't be unique anyways.

I've started throwing the following boilerplate into my components:

constructor(props) {
    super(props);
    this.getId = this.getId.bind(this);
    this.id = 0;
}

getId() {
    return this.id++;
}

which can be used like so:

render() {
    const items = this.props.greetings.map(text => ({
        <li key={this.getId()}>{text}</li>
    }));

    return (
        <ul>
          {items}
        </ul>
    );
}

This is simple, fast, and doesn't have the issues that using the array index has, but I don't know if there are any issue with this approach or better alternatives that I'm overlooking. Is this bad practice? Are there any other simple ways of generating keys that don't have the array index issues?

mgalgs
  • 15,671
  • 11
  • 61
  • 74
  • `key` prop doesn't need to be an integer. You can pass any string to key. So if your `text` prop is unique among the other sibling components you can just pass that as `key` prop. – bennygenel Oct 21 '17 at 21:09
  • @bennygenel this was a contrived example. You can assume that `text` is not guaranteed to be unique. – mgalgs Oct 22 '17 at 01:49

1 Answers1

1

This is what the docs on Reconciliation have to say on keys

In practice, finding a key is usually not hard. The element you are going to display may already have a unique ID, so the key can just come from your data. When that’s not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. The key only has to be unique among its siblings, not globally unique. As a last resort, you can pass item’s index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.

So I think you are following the suggested approach.

palsrealm
  • 5,083
  • 1
  • 20
  • 25
  • It seems like my approach wouldn't have the issues with slow reordering, right? Wonder why the docs don't recommend something like this... I guess the one drawback is all the boilerplate, when you don't care much about performance that's hard to justify... – mgalgs Oct 22 '17 at 21:07
  • No, you are safe from slow reordering as you create ids explicitly. The docs do say that you should use the array indices as keys as a last resort. Check out one of the questions I came across which shows what might happen. https://stackoverflow.com/questions/46477711/react-error-when-removing-input-component – palsrealm Oct 22 '17 at 21:21
  • Also, to get around the boilerplate, you can create a HOC which would add an id prop to any component which you might want to use in an array. Just a thought. – palsrealm Oct 22 '17 at 21:23