How It Works Features Pricing Blog Error Guides
Log In Start Free Trial
React · TypeScript/React

Fix Warning: Each child in a list should have a unique "key" prop in React

This warning fires when you render a list of elements without assigning a unique key prop to each item. React uses keys to track which items changed, were added, or removed. Fix it by adding a stable, unique key such as a database ID to each list element instead of using array indices.

Reading the Stack Trace

Warning: Each child in a list should have a unique "key" prop. Check the render method of `ProductList`. See https://reactjs.org/link/warning-keys for more information. at ProductCard (webpack-internal:///./src/components/ProductCard.tsx:6:3) at ProductList (webpack-internal:///./src/components/ProductList.tsx:11:5) at div at App (webpack-internal:///./src/App.tsx:18:1) at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:16305:18) at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:20069:13) at beginWork (node_modules/react-dom/cjs/react-dom.development.js:21587:16) at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:4164:14) at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:4213:16) at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4277:31)

Here's what each line means:

Common Causes

1. No key prop on mapped elements

The .map() call renders components without passing a key prop, so React cannot efficiently reconcile list changes.

export default function ProductList({ products }) {
  return (
    <ul>
      {products.map(product => (
        <ProductCard name={product.name} price={product.price} />
      ))}
    </ul>
  );
}

2. Using array index as key

Using the array index as key causes bugs when items are reordered, inserted, or deleted because indices shift and React reuses the wrong DOM nodes.

export default function ProductList({ products }) {
  return (
    <ul>
      {products.map((product, index) => (
        <ProductCard key={index} name={product.name} price={product.price} />
      ))}
    </ul>
  );
}

3. Duplicate keys in the list

Two or more items share the same key value, causing React to misidentify elements and produce rendering glitches.

export default function ProductList({ products }) {
  return (
    <ul>
      {products.map(product => (
        <ProductCard key={product.category} name={product.name} />
      ))}
    </ul>
  );
}

The Fix

Add a unique and stable key prop to each ProductCard element using the product's database ID. This allows React to correctly identify which items changed and avoid unnecessary re-renders or DOM corruption.

Before (broken)
export default function ProductList({ products }) {
  return (
    <ul>
      {products.map(product => (
        <ProductCard name={product.name} price={product.price} />
      ))}
    </ul>
  );
}
After (fixed)
export default function ProductList({ products }) {
  return (
    <ul>
      {products.map(product => (
        <ProductCard key={product.id} name={product.name} price={product.price} />
      ))}
    </ul>
  );
}

Testing the Fix

import { render, screen } from '@testing-library/react';
import ProductList from './ProductList';

describe('ProductList', () => {
  const products = [
    { id: '1', name: 'Widget', price: 9.99 },
    { id: '2', name: 'Gadget', price: 19.99 },
  ];

  it('renders all products without key warnings', () => {
    const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
    render(<ProductList products={products} />);
    expect(spy).not.toHaveBeenCalledWith(
      expect.stringContaining('unique "key" prop')
    );
    spy.mockRestore();
  });

  it('renders each product name', () => {
    render(<ProductList products={products} />);
    expect(screen.getByText('Widget')).toBeInTheDocument();
    expect(screen.getByText('Gadget')).toBeInTheDocument();
  });

  it('handles an empty product list', () => {
    render(<ProductList products={[]} />);
    expect(screen.queryByRole('listitem')).not.toBeInTheDocument();
  });
});

Run your tests:

npm test

Pushing Through CI/CD

git checkout -b fix/react-key-prop-error,git add src/components/ProductList.tsx src/components/__tests__/ProductList.test.tsx,git commit -m "fix: add unique key prop to mapped ProductCard elements",git push origin fix/react-key-prop-error

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - run: npm run build

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

npm install bugstack-sdk

Step 2: Initialize

import { initBugStack } from 'bugstack-sdk'

initBugStack({ apiKey: process.env.BUGSTACK_API_KEY })

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Run the test suite locally to confirm no key prop warnings appear.
  2. Open a pull request with the key prop additions.
  3. Wait for CI checks to pass on the PR.
  4. Have a teammate review and approve the PR.
  5. Merge to main and verify the fix in staging before promoting to production.

Frequently Asked Questions

BugStack runs the fix through your existing test suite, generates additional edge-case tests for list rendering, and validates that no other components are affected before marking it safe to deploy.

BugStack never pushes directly to production. Every fix goes through a pull request with full CI checks, so your team can review it before merging.

Index keys cause subtle bugs when items are reordered, inserted, or deleted. React will reuse DOM nodes for the wrong data, leading to stale input values and broken animations.

You can generate stable keys using a combination of unique fields, such as name plus timestamp. As a last resort, use a library like uuid to assign IDs when the data is first created.