Codepath

Rendering Lists

Often, you will want to display multiple similar components from a collection of data. React relies on JavaScript features such as for loops and the array map function to render a list of components.

For example, say that we have the following array of products:

const products = [
  {
    id: 1,
    title: 'Bread'
  },
  {
    id: 2,
    title: 'Milk'
  },
  {
    id: 3,
    title: 'Cheese'
  },
  {
    id: 4,
    title: 'Noodles'
  },
];

Then, inside your component, use the map()const function to transform the data array into an array of UI items:

const productItems = products.map((product) => (
  <li key={product.id}>
    {product.title}
  </li>
));

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

The example above will display a bullet list of products. One thing to take note is the key attribute on the <li> element. When rendering a list on React, a key attribute should be provide which will uniquely identify the item among its siblings.

React relies on the provided key to understand which items, if any, have changed, are added, or removed throughout the component renders.

đź’ˇ The best way to pick a key is to use a string that uniquely identifies a list item among other items in the list. Usually, a key should be coming from your database.

What to do if you do not have a key

When your data doesn’t have a stable ID for the rendered items, you may use the item index on the array as a key.

const productItems = products.map((product, index) => (
  // Only do this if items have no stable IDs
  <li key={index}>
    {product.title}
  </li>
));

⚠️ This is a last resort strategy that should only be use if the data has no unique identifier and the order of the items are not going to change. Else, this can negatively impact performance and may cause component state issues.

Rules of keys

  • Keys must be unique among siblings. That said, they do not need to be globally unique. I.e: use the same keys to produce two different lists.

    function Blog(props) {
      const sidebar = (
        <ul>
          {props.posts.map((post) =>
            <li key={post.id}>
              {post.title}
            </li>
          )}
        </ul>
      );
      const content = props.posts.map((post) =>
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      );
      return (
        <div>
          {sidebar}
          <hr />
          {content}
        </div>
      );
    }
  • Keys must not change. Don’t generate them while rendering. E.g:

    <Post key={Math.random()} ... />

Learn more

Fork me on GitHub