In a React app, two unrelated lists on the same page each give their rows the key values 1, 2 and 3. Is that a problem? Explain the scope in which React actually compares keys.
answer
- think about where the comparison happens
- one parent's children at a time
- lookup built only from previous siblings
- duplicates matter only inside one list
- same key, new parent, still remounts
basics
~10 sNo. React compares keys only among the children of one parent, during that parent's re-render. Separate lists may reuse the same key values freely; only duplicate keys inside a single list are a bug.
solid answer
~50 sKeys are local names, not global identifiers. When a parent re-renders, React pairs its new child list against the child list that same parent produced last time, and the lookup it builds contains only those previous siblings. Nothing outside that child set is ever consulted, so `key={1}` in one list and `key={1}` in another never interact. What does matter is uniqueness *within* one list: two siblings with the same key produce the "Encountered two children with the same key" warning, because only one previous fiber can be paired with a given key and the other element is treated as new. The flip side is that a key cannot carry anything across parents — render the same element with the same key under a different parent and React still unmounts it and mounts a fresh one, because the two parents' child sets are reconciled independently.
go deeper
Be ready to say that keys only need to be unique among siblings, and that two separate lists can safely use the same key values. Mention that duplicate keys inside one list trigger a React warning.
Explain the mechanism behind the scope: React pairs a parent's new children against that same parent's previous children using a lookup built only from those siblings, which is why nothing outside that child set is ever consulted.
Show the practical consequence in real code: a row moving between two parent lists remounts and loses its state even with an identical key, so any state that must survive the move has to live above both lists or in an external store.
Frame keys as a local identity contract owned by whoever renders the list. Be ready to discuss where item identity should come from when data is merged from several sources, and why compound keys beat globally-unique key schemes.
## What a key names When React renders `<Row key="a" />`, the key is stored on the element and then on the fiber React creates for it. It is not registered anywhere global. Reconciliation runs parent by parent: when a parent re-renders, React takes the new child list it just produced and pairs it against the child list that *same* parent produced on the previous render. To do that it builds a lookup table from the previous children, keyed by their keys. That table contains that one parent's previous children and nothing else. So a key is a name that is valid inside one child list, for the duration of one pairing. "Unique keys" in the React warning always means unique among siblings. ## Consequence 1: reuse across lists is free ```jsx <ul>{users.map((u, i) => <li key={i}>{u.name}</li>)}</ul> <ul>{tags.map((t, i) => <li key={i}>{t}</li>)}</ul> ``` Both lists use the keys `0, 1, 2`. There is no collision, because the two `<ul>` elements are separate parents with separate child sets. You never need to prefix keys with the list name to make them globally unique. (Whether index keys are a good choice at all is a different question — that is about stability across renders, not about scope.) ## Consequence 2: duplicates inside one list are the real bug If one child set contains two elements with the same key, React logs `Encountered two children with the same key`. The pairing is ambiguous: a given previous fiber can be matched at most once, so the second element with that key finds nothing to pair with and is mounted fresh. In practice that shows up as a row that silently loses its state, or updates landing on the wrong row. The fix is to make the key derive from something actually unique in that list — a compound key such as `` `${item.type}-${item.id}` `` when two collections are concatenated into one list. ## Consequence 3: a key cannot move state between parents This is the part candidates get wrong. Consider a row that moves from an "Active" list to an "Archived" list, keeping `key={row.id}`: ```jsx <ul>{active.map(r => <Row key={r.id} row={r} />)}</ul> <ul>{archived.map(r => <Row key={r.id} row={r} />)}</ul> ``` When the row moves, the first `<ul>` reconciles its children and finds no element for that key, so it deletes that fiber — running its effect cleanups and detaching its refs. The second `<ul>` reconciles its own children and finds a key it has never seen, so it mounts a brand-new fiber with fresh hook state. The identical key value is irrelevant: the two parents never look at each other's children. Component state survives a move only inside one parent's child list. ## Consequence 4: key is not a prop React consumes `key` itself; it is not passed through to the component, so a component cannot read `props.key`. If the child needs its identifier, pass it a second time as an ordinary prop: ```jsx <Row key={row.id} id={row.id} /> ``` ## Keys are strings React coerces a key to a string, so `key={1}` and `key="1"` are the same key. That matters when a list mixes numeric ids with string ids that happen to stringify identically — those count as duplicates, warning and all. ## The shape of a good answer Say that the comparison is per-parent, that the lookup is built only from that parent's previous children, and then draw the two consequences: cross-list reuse is harmless, and a shared key across parents preserves nothing. That demonstrates you know where the matching happens, not just that keys "help React".
- What actually goes wrong when two siblings in the same list end up with the same key?React logs "Encountered two children with the same key" and the pairing becomes ambiguous: a previous fiber can be matched only once, so the second element is treated as new and mounts fresh — losing its state — while updates can land on the other row. Fix it at the source with a compound key such as `${item.type}-${item.id}`.
- Can a component read its own key from props?No. React consumes `key` when it creates the element, so it never reaches the component's props. If the child needs the identifier, pass it a second time as a normal prop, for example `<Row key={row.id} id={row.id} />`.
- Are keys compared as numbers or as strings?As strings — React coerces the key value when it creates the element, so `key={1}` and `key="1"` are the same key. In a list that mixes numeric and string identifiers, two values that stringify identically count as duplicates and trigger the duplicate-key warning.
saying these in an interview costs you the question
- Keys have to be unique across the whole application
- Keeping the same key moves a component's state to another parent
- A component can read its own key from props.key
- Duplicate keys are only a lint warning, harmless at runtime
- React compares keys against every mounted component