About React Keys

React allows specifying a key property on components to help React identify and track their identities across renders.

Iterating over Arrays

Consider an EditableFruit component — a stateful component with side effects — to demonstrate different keying approaches:

function EditableFruit({ value: initialValue }) {
  const [value, setValue] = useState(initialValue);

  // "once" effect that will only happen on mount
  useEffect(() => console.log("init", initialValue));

  return (
    <div>
      <label>{initialValue}</label>
      <input value={value} onChange={(e) => setValue(e.currentTarget.value)} />
    </div>
  );
}

Which is then rendered in a list:

function FruitList({ fruits }: { fruits: string[] }) {
  return (
    <div>
      {fruits.map((fruit) => (
        <EditableFruit key={TODO} value={fruit} />
      ))}
    </div>
  );
}

Using a Unique Key

When elements possess guaranteed-unique identifiers, always use those. This allows React to properly associate DOM elements with array items, even when order changes. Adding AVOCADO in the middle logs init AVOCADO as expected.

Using the Index

As a last resort, index-based keys can work when stable IDs don’t exist. However, this approach prevents React from semantically identifying elements, potentially causing bugs with stateful components.

Adding AVOCADO in the middle produces unexpected behavior — it logs init BANANA and renders inputs with values APPLE, BANANA, and BANANA.

The ESLint rule react/no-array-index-key flags this pattern, encouraging developers to acknowledge the risk explicitly.

Using Index Joined with a Unique Key

A composite key like ${fruit}-${index} avoids state misassociation but carries a performance penalty. React must recalculate diffs more aggressively when using this pattern, making it suitable only when performance constraints permit. Plus, state is lost when the order of items changes.

Not Providing a Key

Omitting key entirely behaves identically to using the index. The react/jsx-key ESLint rule detects this, prompting conscious decision-making. Newer versions of React will also log a warning.

Resetting a Component’s State

key can also serve as a forceful mechanism for resetting component state:

function Example() {
  const [nonce, setNonce] = useState(Date.now());

  return (
    <div>
      <Button onClick={() => setNonce(Date.now())} />
      <Universe key={nonce} />
    </div>
  );
}

Changing the key forces React to unmount and remount the component, clearing all internal state.