Logo
Published on

React Keys

Authors
Keys

React keys

What is "key" prop and what is the benefit of using it in arrays of elements?

  • A key is a special attribute you should include when mapping over arrays to render data.
  • Key prop helps React identify which items have changed, are added, or are removed.
  • Keys should be unique among its siblings. Most often we use ID from our data as a key.
  • Using indexes for keys is not recommended if the order of items may change. This can negatively impact performance and may cause issues with component state.

Rules of keys

  • Keys must be unique among siblings. However, it’s okay to use the same keys for JSX nodes in different arrays.
  • Keys should not change or be generated while rendering (on the fly) e.g. with key={Math.random()} or array indexes. This will cause keys to never match up between renders, leading to all your components and DOM being recreated every time. Not only is this slow, but it will also lose any user input inside the list of items. Instead, use a stable ID based on the data.

Take a close look at the below example where we have React component called ListWithoutKeys that renders dynamic list without stable key. Instead of stable id, we are using array index prop.

import { useState, createElement } from "react";

const dataList = [
    { type: "li", props: { className: "list_item" }, children: "Item #0" },
    // ...
];

const ListWithoutKeys = () => {
    const [list, setList] = useState(dataList);

    const handleElementUnshift = () =>
        setList((prevList) => [
            { ...prevList[0], children: `Item #${prevList.length}` },
            ...prevList,
        ]);

    return (
        <div className="card">
            <ul>
                {list.map((el, index) =>
                    // using index as a `key`
                    createElement(el.type, { ...el.props, key: index }, el.children)
                )}
            </ul>
            <button onClick={handleElementUnshift}>Add new element to the top</button>
        </div>
    );
};
Indexes

As you may see when we click on Add button, whole list gets re-rendered, but we added only one item. This happened because there are no stable keys, on the initial render element with the title "Item #0" that has 0 value as key. And after adding a new element to the list, React re-render component and element with the title "Item #0" now has 1 value as key, and React can't identify what exactly changed and re-renders whole list. To fix this, just add a stable key prop that doesn't change while rendering.

import { useState, createElement } from "react";

// idHub is used only for demonstration
const dataList = [
    { type: "li", props: { className: "list_item", key: idHub[0] }, children: "Item #0" },
    // ...
];

const ListWithKeys = () => {
    const [list, setList] = useState(dataList);

    const handleElementUnshift = () =>
        setList((prevList) => [
            {
                ...prevList[0],
                props: { ...prevList[0].props, key: idHub[prevList.length] },
                children: `Item #${prevList.length}`,
            },
            ...prevList,
        ]);

    return (
        <div className="card">
            <ul>{list.map((el) => createElement(el.type, el.props, el.children))}</ul>
            <button onClick={handleElementUnshift}>Add new element to the top</button>
        </div>
    );
};
Unique_Keys

As you may see only newly added element re-rendered, React is smart enough to figure out what changed.

Why does React need keys?

Imagine that files on your desktop didn’t have names. Instead, you’d refer to them by their order — the first file, the second file, and so on. You could get used to it, but once you delete a file, it would get confusing. The second file would become the first file, the third file would be the second file, and so on.

Keys help React uniquely identify an item between its siblings. When the position of the element changes, key lets React identify what happened with this item between re-rendering.

Here is a small example of what could happen when using list without key property in React.

  1. Write something inside input
  2. Try to remove remove first input.
    - See what happen? Doesn't matter which input you are trying to remove. From view always gonna be removed last one in the list.
  3. Add key={item.id} property to the list and try again. See? Works just fine.