2

I'd love to know how to generate a dynamic table within react, but provide each of my rows of data with proper keys for react to do it's magical stuff.

Here is an example of simple table/row generation I'm doing.

const listItems = (row, index) => (
  row.map(item => (
    <td key={item + index}>
      {item}
    </td>
  ))
);

const listRows = (rows) => {
  if (!rows) {
    return [];
  }
  return rows.map((row, index) => {
    const key = row[0] + index;
    return (
      <tr key={key}>
        {listItems(row)}
      </tr>
    );
  });
};
const listHeaderItems = (headers) => {
  if (!headers) {
    return [];
  }
  return headers.map((item, key) => (
    <th key={key}>
      {item}
    </th>
  ));
};

The 2 problems with this:

  1. Using field values as keys, with arbitrary, duplicate and sometimes empty values are subpar as keys. React no likey.
  2. My solution to problem 1 creates a new problem. Using array index values as keys. This is seen as a no-no from an eslint perspective and considered an anti-pattern because of performance side effects. no-array-index-key , React array index anti pattern

I'd love to help react be more magical with its shadow dom awesomeness, but I'm a little confused on how to achieve this.

In summary:

How do I provide react unique key indexes for table data that is not useful as keys?

Justin
  • 2,940
  • 3
  • 25
  • 43
  • The problem with index is that if you are mutating your table (adding rows, deleting rows), the behavior won't work correctly. However, if you are just displaying data, this will not be a problem to use indexes, just override the rule. If you are creating data, add a random uuid to the data to avoid any problem – Axnyff Sep 28 '18 at 14:45
  • Generate GUIDs for each element [like this](https://stackoverflow.com/q/105034/4881192). – Adam Sep 28 '18 at 14:49

2 Answers2

0

I personally use short-id to generate keys.

It generates a series of random keys you can use.

Basically replace all of your key={...} with key={shortid.generate()}

dance2die
  • 35,807
  • 39
  • 131
  • 194
  • This is close, but falls into the similar category of being an anti-pattern as the keys won't persist. https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318 – Justin Sep 28 '18 at 15:36
  • @Justin The answer stems from the part of the question `not useful as keys`. And regarding the `persistence`, would you update the question to mention that keys should persist? One more thing, would you kindly point out how my answer is an anti-pattern? I read the linked post and would like to know why – dance2die Sep 28 '18 at 15:53
  • Sure happy to clarify on that. In reference to the medium post, he mentioned "Each such item should have a permanent and unique property. " Meaning if you don't have a key that persists, then you are not allowing react to do the peformance enhancements it wants, as you'd be changing the key every time the table is rendered. – Justin Sep 28 '18 at 20:53
  • Thank you @Justin. I appreciate the clarification. I will leave the question downvoted as your comment has been helpful. Let me know if I should delete this answer or not. – dance2die Sep 28 '18 at 22:41
  • 1
    All good, I think its still useful to have as some folks will still think about going this route. Thanks for your input! – Justin Oct 01 '18 at 17:10
0

One solution would be to add an unique ID to the items you are mapping and use it as key.

Another one to use something like a UUID-generator

Lumpenstein
  • 1,250
  • 1
  • 10
  • 27
  • Yeah I'm guessing generating uuid's is probably the way to go. Though it sounds like I'll need to modify each element object in each item of the array. And do it in some sort of preprocessing function in order to make it persist. – Justin Sep 28 '18 at 15:29