[{"data":1,"prerenderedAt":1554},["ShallowReactive",2],{"blog-\u002Fblog\u002Freact-lists-keys-guide":3},{"id":4,"title":5,"body":6,"description":1538,"difficulty":1539,"extension":1540,"framework":1541,"frameworkSlug":1542,"meta":1543,"navigation":430,"order":100,"path":1545,"qaPath":1546,"seo":1547,"stem":1548,"subtopic":1549,"topic":1550,"topicSlug":1551,"updated":1552,"__hash__":1553},"blog\u002Fblog\u002Freact-lists-keys-guide.md","React Lists and Keys — A Complete Interview Guide",{"type":7,"value":8,"toc":1524},"minimark",[9,14,23,171,182,186,199,205,225,228,232,235,242,299,310,332,337,376,380,401,557,571,575,578,600,680,683,687,699,821,825,839,959,974,978,981,1041,1044,1112,1116,1119,1285,1291,1295,1303,1455,1465,1469,1472,1480,1483,1487,1490,1517,1520],[10,11,13],"h2",{"id":12},"rendering-lists-in-react","Rendering lists in React",[15,16,17,18,22],"p",{},"The standard pattern is ",[19,20,21],"code",{},"Array.map"," — transform a data array into an array of\nReact elements, which React renders as children.",[24,25,30],"pre",{"className":26,"code":27,"language":28,"meta":29,"style":29},"language-jsx shiki shiki-themes github-light github-dark","function ProductList({ products }) {\n  return (\n    \u003Cul>\n      {products.map(product => (\n        \u003Cli key={product.id}>\n          \u003Cstrong>{product.name}\u003C\u002Fstrong> — ${product.price}\n        \u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  )\n}\n","jsx","",[19,31,32,56,65,78,98,116,133,143,149,159,165],{"__ignoreMap":29},[33,34,37,41,45,49,53],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"szBVR","function",[33,42,44],{"class":43},"sScJk"," ProductList",[33,46,48],{"class":47},"sVt8B","({ ",[33,50,52],{"class":51},"s4XuR","products",[33,54,55],{"class":47}," }) {\n",[33,57,59,62],{"class":35,"line":58},2,[33,60,61],{"class":39},"  return",[33,63,64],{"class":47}," (\n",[33,66,68,71,75],{"class":35,"line":67},3,[33,69,70],{"class":47},"    \u003C",[33,72,74],{"class":73},"s9eBZ","ul",[33,76,77],{"class":47},">\n",[33,79,81,84,87,90,93,96],{"class":35,"line":80},4,[33,82,83],{"class":47},"      {products.",[33,85,86],{"class":43},"map",[33,88,89],{"class":47},"(",[33,91,92],{"class":51},"product",[33,94,95],{"class":39}," =>",[33,97,64],{"class":47},[33,99,101,104,107,110,113],{"class":35,"line":100},5,[33,102,103],{"class":47},"        \u003C",[33,105,106],{"class":73},"li",[33,108,109],{"class":43}," key",[33,111,112],{"class":39},"=",[33,114,115],{"class":47},"{product.id}>\n",[33,117,119,122,125,128,130],{"class":35,"line":118},6,[33,120,121],{"class":47},"          \u003C",[33,123,124],{"class":73},"strong",[33,126,127],{"class":47},">{product.name}\u003C\u002F",[33,129,124],{"class":73},[33,131,132],{"class":47},"> — ${product.price}\n",[33,134,136,139,141],{"class":35,"line":135},7,[33,137,138],{"class":47},"        \u003C\u002F",[33,140,106],{"class":73},[33,142,77],{"class":47},[33,144,146],{"class":35,"line":145},8,[33,147,148],{"class":47},"      ))}\n",[33,150,152,155,157],{"class":35,"line":151},9,[33,153,154],{"class":47},"    \u003C\u002F",[33,156,74],{"class":73},[33,158,77],{"class":47},[33,160,162],{"class":35,"line":161},10,[33,163,164],{"class":47},"  )\n",[33,166,168],{"class":35,"line":167},11,[33,169,170],{"class":47},"}\n",[15,172,173,174,177,178,181],{},"Every element returned from ",[19,175,176],{},".map()"," must have a ",[19,179,180],{},"key"," prop. Without it, React\nlogs a warning in development and falls back to positional matching — which\nproduces incorrect output whenever the list changes.",[10,183,185],{"id":184},"what-the-key-prop-actually-does","What the key prop actually does",[15,187,188,190,191,194,195,198],{},[19,189,180],{}," is a ",[124,192,193],{},"special React prop"," — not forwarded to the component, not readable\nvia ",[19,196,197],{},"props.key"," — that exists solely for React's reconciler. It gives each\nelement in a list a stable identity.",[15,200,201,202,204],{},"During reconciliation, React builds a map of the previous render's list keyed\nby ",[19,203,180],{},". When the new render arrives, React looks up each element's key in\nthat map:",[74,206,207,213,219],{},[106,208,209,212],{},[124,210,211],{},"Same key, same type"," → update props in place (potentially reorder the DOM node).",[106,214,215,218],{},[124,216,217],{},"New key"," → mount a new component.",[106,220,221,224],{},[124,222,223],{},"Key gone"," → unmount the old component.",[15,226,227],{},"Without keys, React matches elements by position: old index 0 = new index 0.\nThis fails as soon as items are inserted, deleted, or reordered.",[10,229,231],{"id":230},"the-index-as-key-bug","The index-as-key bug",[15,233,234],{},"This is one of the most frequently tested React correctness questions.",[15,236,237,238,241],{},"Using array index as a key breaks when the list can be ",[124,239,240],{},"sorted, filtered,\nor have items added or deleted",":",[24,243,245],{"className":26,"code":244,"language":28,"meta":29,"style":29},"\u002F\u002F ❌ Index keys — dangerous for mutable lists\n{todos.map((todo, i) => \u003CTodoItem key={i} todo={todo} \u002F>)}\n",[19,246,247,253],{"__ignoreMap":29},[33,248,249],{"class":35,"line":36},[33,250,252],{"class":251},"sJ8bj","\u002F\u002F ❌ Index keys — dangerous for mutable lists\n",[33,254,255,258,260,263,266,269,272,275,278,281,285,287,289,292,294,296],{"class":35,"line":58},[33,256,257],{"class":47},"{todos.",[33,259,86],{"class":43},[33,261,262],{"class":47},"((",[33,264,265],{"class":51},"todo",[33,267,268],{"class":47},", ",[33,270,271],{"class":51},"i",[33,273,274],{"class":47},") ",[33,276,277],{"class":39},"=>",[33,279,280],{"class":47}," \u003C",[33,282,284],{"class":283},"sj4cs","TodoItem",[33,286,109],{"class":43},[33,288,112],{"class":39},[33,290,291],{"class":47},"{i} ",[33,293,265],{"class":43},[33,295,112],{"class":39},[33,297,298],{"class":47},"{todo} \u002F>)}\n",[15,300,301,302,305,306,309],{},"The scenario that breaks: you have three items ",[19,303,304],{},"[Alice, Bob, Carol]",". You\ndelete Alice. The list becomes ",[19,307,308],{},"[Bob, Carol]",". With index keys:",[74,311,312,326,329],{},[106,313,314,315,318,319,321,322,325],{},"Key ",[19,316,317],{},"0"," was Alice → now key ",[19,320,317],{}," is Bob. React thinks the Alice component\n(now at index 0) received new props for Bob. React updates the props but\n",[124,323,324],{},"keeps Alice's state",".",[106,327,328],{},"Controlled input showing Alice's draft text now shows Bob's name but still\ncontains Alice's partially-typed message.",[106,330,331],{},"Animated entrance effects trigger for Bob and Carol instead of Alice leaving.",[15,333,334],{},[124,335,336],{},"The fix:",[24,338,340],{"className":26,"code":339,"language":28,"meta":29,"style":29},"\u002F\u002F ✅ Stable id from the data\n{todos.map(todo => \u003CTodoItem key={todo.id} todo={todo} \u002F>)}\n",[19,341,342,347],{"__ignoreMap":29},[33,343,344],{"class":35,"line":36},[33,345,346],{"class":251},"\u002F\u002F ✅ Stable id from the data\n",[33,348,349,351,353,355,357,359,361,363,365,367,370,372,374],{"class":35,"line":58},[33,350,257],{"class":47},[33,352,86],{"class":43},[33,354,89],{"class":47},[33,356,265],{"class":51},[33,358,95],{"class":39},[33,360,280],{"class":47},[33,362,284],{"class":283},[33,364,109],{"class":43},[33,366,112],{"class":39},[33,368,369],{"class":47},"{todo.id} ",[33,371,265],{"class":43},[33,373,112],{"class":39},[33,375,298],{"class":47},[10,377,379],{"id":378},"what-makes-a-good-key","What makes a good key",[381,382,383,389,395],"ol",{},[106,384,385,388],{},[124,386,387],{},"Unique among siblings"," — within a single list, no two siblings share a key.\nThe same key can appear in a different list.",[106,390,391,394],{},[124,392,393],{},"Stable"," — the same data item has the same key on every render.",[106,396,397,400],{},[124,398,399],{},"String or number"," — React converts numbers to strings internally.",[24,402,404],{"className":26,"code":403,"language":28,"meta":29,"style":29},"\u002F\u002F ✅ Database primary key\n\u003CRow key={row.id} \u002F>\n\n\u002F\u002F ✅ Slug, if guaranteed unique within the list\n\u003CTab key={tab.slug} \u002F>\n\n\u002F\u002F ✅ Composite key when no single field is unique\n\u003CCell key={`${row.id}-${col.name}`} \u002F>\n\n\u002F\u002F ❌ Math.random() — new key every render → unmount\u002Fremount on every render\n\u003CItem key={Math.random()} \u002F>\n\n\u002F\u002F ❌ Array index for a mutable list\n\u003CItem key={i} \u002F>\n",[19,405,406,411,426,432,437,451,455,460,503,507,512,532,537,543],{"__ignoreMap":29},[33,407,408],{"class":35,"line":36},[33,409,410],{"class":251},"\u002F\u002F ✅ Database primary key\n",[33,412,413,416,419,421,423],{"class":35,"line":58},[33,414,415],{"class":47},"\u003C",[33,417,418],{"class":283},"Row",[33,420,109],{"class":43},[33,422,112],{"class":39},[33,424,425],{"class":47},"{row.id} \u002F>\n",[33,427,428],{"class":35,"line":67},[33,429,431],{"emptyLinePlaceholder":430},true,"\n",[33,433,434],{"class":35,"line":80},[33,435,436],{"class":251},"\u002F\u002F ✅ Slug, if guaranteed unique within the list\n",[33,438,439,441,444,446,448],{"class":35,"line":100},[33,440,415],{"class":47},[33,442,443],{"class":283},"Tab",[33,445,109],{"class":43},[33,447,112],{"class":39},[33,449,450],{"class":47},"{tab.slug} \u002F>\n",[33,452,453],{"class":35,"line":118},[33,454,431],{"emptyLinePlaceholder":430},[33,456,457],{"class":35,"line":135},[33,458,459],{"class":251},"\u002F\u002F ✅ Composite key when no single field is unique\n",[33,461,462,464,467,469,471,474,478,481,483,486,489,492,494,497,500],{"class":35,"line":145},[33,463,415],{"class":47},[33,465,466],{"class":283},"Cell",[33,468,109],{"class":43},[33,470,112],{"class":39},[33,472,473],{"class":47},"{",[33,475,477],{"class":476},"sZZnC","`${",[33,479,480],{"class":47},"row",[33,482,325],{"class":476},[33,484,485],{"class":47},"id",[33,487,488],{"class":476},"}-${",[33,490,491],{"class":47},"col",[33,493,325],{"class":476},[33,495,496],{"class":47},"name",[33,498,499],{"class":476},"}`",[33,501,502],{"class":47},"} \u002F>\n",[33,504,505],{"class":35,"line":151},[33,506,431],{"emptyLinePlaceholder":430},[33,508,509],{"class":35,"line":161},[33,510,511],{"class":251},"\u002F\u002F ❌ Math.random() — new key every render → unmount\u002Fremount on every render\n",[33,513,514,516,519,521,523,526,529],{"class":35,"line":167},[33,515,415],{"class":47},[33,517,518],{"class":283},"Item",[33,520,109],{"class":43},[33,522,112],{"class":39},[33,524,525],{"class":47},"{Math.",[33,527,528],{"class":43},"random",[33,530,531],{"class":47},"()} \u002F>\n",[33,533,535],{"class":35,"line":534},12,[33,536,431],{"emptyLinePlaceholder":430},[33,538,540],{"class":35,"line":539},13,[33,541,542],{"class":251},"\u002F\u002F ❌ Array index for a mutable list\n",[33,544,546,548,550,552,554],{"class":35,"line":545},14,[33,547,415],{"class":47},[33,549,518],{"class":283},[33,551,109],{"class":43},[33,553,112],{"class":39},[33,555,556],{"class":47},"{i} \u002F>\n",[15,558,559,560,562,563,566,567,570],{},"Generating keys inside ",[19,561,176],{}," with ",[19,564,565],{},"Math.random()"," or ",[19,568,569],{},"Date.now()"," is worse\nthan no key at all — it forces React to unmount and remount every item on every\nrender, discarding all state and running all effects twice.",[10,572,574],{"id":573},"when-index-keys-are-safe","When index keys are safe",[15,576,577],{},"The React team's guidance: three conditions must all be true.",[381,579,580,587,594],{},[106,581,582,583,586],{},"The list is ",[124,584,585],{},"static"," — no insertions, deletions, or reorderings.",[106,588,589,590,593],{},"Items have ",[124,591,592],{},"no stable IDs"," in the data.",[106,595,589,596,599],{},[124,597,598],{},"no internal state"," — they are pure display.",[24,601,603],{"className":26,"code":602,"language":28,"meta":29,"style":29},"\u002F\u002F Acceptable: static ordered list, no ids, no state\nconst STEPS = ['Install dependencies', 'Configure environment', 'Run migrations']\n{STEPS.map((step, i) => \u003Cli key={i}>{step}\u003C\u002Fli>)}\n",[19,604,605,610,640],{"__ignoreMap":29},[33,606,607],{"class":35,"line":36},[33,608,609],{"class":251},"\u002F\u002F Acceptable: static ordered list, no ids, no state\n",[33,611,612,615,618,621,624,627,629,632,634,637],{"class":35,"line":58},[33,613,614],{"class":39},"const",[33,616,617],{"class":283}," STEPS",[33,619,620],{"class":39}," =",[33,622,623],{"class":47}," [",[33,625,626],{"class":476},"'Install dependencies'",[33,628,268],{"class":47},[33,630,631],{"class":476},"'Configure environment'",[33,633,268],{"class":47},[33,635,636],{"class":476},"'Run migrations'",[33,638,639],{"class":47},"]\n",[33,641,642,644,647,649,651,653,656,658,660,662,664,666,668,670,672,675,677],{"class":35,"line":67},[33,643,473],{"class":47},[33,645,646],{"class":283},"STEPS",[33,648,325],{"class":47},[33,650,86],{"class":43},[33,652,262],{"class":47},[33,654,655],{"class":51},"step",[33,657,268],{"class":47},[33,659,271],{"class":51},[33,661,274],{"class":47},[33,663,277],{"class":39},[33,665,280],{"class":47},[33,667,106],{"class":73},[33,669,109],{"class":43},[33,671,112],{"class":39},[33,673,674],{"class":47},"{i}>{step}\u003C\u002F",[33,676,106],{"class":73},[33,678,679],{"class":47},">)}\n",[15,681,682],{},"When in doubt, the data should have IDs. Generate them at the source, not at\nrender time.",[10,684,686],{"id":685},"where-to-place-the-key","Where to place the key",[15,688,689,691,692,695,696,698],{},[19,690,180],{}," goes on the ",[124,693,694],{},"outermost element"," returned from the ",[19,697,176],{}," callback:",[24,700,702],{"className":26,"code":701,"language":28,"meta":29,"style":29},"\u002F\u002F ✅ key on the outer element\n{items.map(item => (\n  \u003CProductCard key={item.id} item={item} \u002F>\n))}\n\n\u002F\u002F ❌ key on an inner element — React doesn't see it for list tracking\n{items.map(item => (\n  \u003Cdiv>\n    \u003CProductCard key={item.id} item={item} \u002F>  {\u002F* wrong *\u002F}\n  \u003C\u002Fdiv>\n))}\n",[19,703,704,709,725,747,752,756,761,775,784,808,817],{"__ignoreMap":29},[33,705,706],{"class":35,"line":36},[33,707,708],{"class":251},"\u002F\u002F ✅ key on the outer element\n",[33,710,711,714,716,718,721,723],{"class":35,"line":58},[33,712,713],{"class":47},"{items.",[33,715,86],{"class":43},[33,717,89],{"class":47},[33,719,720],{"class":51},"item",[33,722,95],{"class":39},[33,724,64],{"class":47},[33,726,727,730,733,735,737,740,742,744],{"class":35,"line":67},[33,728,729],{"class":47},"  \u003C",[33,731,732],{"class":283},"ProductCard",[33,734,109],{"class":43},[33,736,112],{"class":39},[33,738,739],{"class":47},"{item.id} ",[33,741,720],{"class":43},[33,743,112],{"class":39},[33,745,746],{"class":47},"{item} \u002F>\n",[33,748,749],{"class":35,"line":80},[33,750,751],{"class":47},"))}\n",[33,753,754],{"class":35,"line":100},[33,755,431],{"emptyLinePlaceholder":430},[33,757,758],{"class":35,"line":118},[33,759,760],{"class":251},"\u002F\u002F ❌ key on an inner element — React doesn't see it for list tracking\n",[33,762,763,765,767,769,771,773],{"class":35,"line":135},[33,764,713],{"class":47},[33,766,86],{"class":43},[33,768,89],{"class":47},[33,770,720],{"class":51},[33,772,95],{"class":39},[33,774,64],{"class":47},[33,776,777,779,782],{"class":35,"line":145},[33,778,729],{"class":47},[33,780,781],{"class":73},"div",[33,783,77],{"class":47},[33,785,786,788,790,792,794,796,798,800,803,806],{"class":35,"line":151},[33,787,70],{"class":47},[33,789,732],{"class":283},[33,791,109],{"class":43},[33,793,112],{"class":39},[33,795,739],{"class":47},[33,797,720],{"class":43},[33,799,112],{"class":39},[33,801,802],{"class":47},"{item} \u002F>  {",[33,804,805],{"class":251},"\u002F* wrong *\u002F",[33,807,170],{"class":47},[33,809,810,813,815],{"class":35,"line":161},[33,811,812],{"class":47},"  \u003C\u002F",[33,814,781],{"class":73},[33,816,77],{"class":47},[33,818,819],{"class":35,"line":167},[33,820,751],{"class":47},[10,822,824],{"id":823},"fragments-in-lists","Fragments in lists",[15,826,827,828,831,832,835,836,838],{},"When each list item needs to render multiple sibling elements without a wrapper\nDOM node, use ",[19,829,830],{},"\u003CReact.Fragment key={id}>",". The short syntax ",[19,833,834],{},"\u003C>"," doesn't accept\na ",[19,837,180],{}," prop.",[24,840,842],{"className":26,"code":841,"language":28,"meta":29,"style":29},"function DefinitionList({ terms }) {\n  return (\n    \u003Cdl>\n      {terms.map(term => (\n        \u003CReact.Fragment key={term.id}>\n          \u003Cdt>{term.word}\u003C\u002Fdt>\n          \u003Cdd>{term.definition}\u003C\u002Fdd>\n        \u003C\u002FReact.Fragment>\n      ))}\n    \u003C\u002Fdl>\n  )\n}\n",[19,843,844,858,864,873,889,903,917,931,939,943,951,955],{"__ignoreMap":29},[33,845,846,848,851,853,856],{"class":35,"line":36},[33,847,40],{"class":39},[33,849,850],{"class":43}," DefinitionList",[33,852,48],{"class":47},[33,854,855],{"class":51},"terms",[33,857,55],{"class":47},[33,859,860,862],{"class":35,"line":58},[33,861,61],{"class":39},[33,863,64],{"class":47},[33,865,866,868,871],{"class":35,"line":67},[33,867,70],{"class":47},[33,869,870],{"class":73},"dl",[33,872,77],{"class":47},[33,874,875,878,880,882,885,887],{"class":35,"line":80},[33,876,877],{"class":47},"      {terms.",[33,879,86],{"class":43},[33,881,89],{"class":47},[33,883,884],{"class":51},"term",[33,886,95],{"class":39},[33,888,64],{"class":47},[33,890,891,893,896,898,900],{"class":35,"line":100},[33,892,103],{"class":47},[33,894,895],{"class":283},"React.Fragment",[33,897,109],{"class":43},[33,899,112],{"class":39},[33,901,902],{"class":47},"{term.id}>\n",[33,904,905,907,910,913,915],{"class":35,"line":118},[33,906,121],{"class":47},[33,908,909],{"class":73},"dt",[33,911,912],{"class":47},">{term.word}\u003C\u002F",[33,914,909],{"class":73},[33,916,77],{"class":47},[33,918,919,921,924,927,929],{"class":35,"line":135},[33,920,121],{"class":47},[33,922,923],{"class":73},"dd",[33,925,926],{"class":47},">{term.definition}\u003C\u002F",[33,928,923],{"class":73},[33,930,77],{"class":47},[33,932,933,935,937],{"class":35,"line":145},[33,934,138],{"class":47},[33,936,895],{"class":283},[33,938,77],{"class":47},[33,940,941],{"class":35,"line":151},[33,942,148],{"class":47},[33,944,945,947,949],{"class":35,"line":161},[33,946,154],{"class":47},[33,948,870],{"class":73},[33,950,77],{"class":47},[33,952,953],{"class":35,"line":167},[33,954,164],{"class":47},[33,956,957],{"class":35,"line":534},[33,958,170],{"class":47},[15,960,961,962,965,966,969,970,973],{},"Using ",[19,963,964],{},"\u003Cdiv>"," instead would produce ",[19,967,968],{},"\u003Cdl>\u003Cdiv>\u003Cdt>…\u003C\u002Fdt>\u003Cdd>…\u003C\u002Fdd>\u003C\u002Fdiv>\u003C\u002Fdl>",",\nwhich is invalid HTML. The Fragment produces ",[19,971,972],{},"\u003Cdl>\u003Cdt>…\u003C\u002Fdt>\u003Cdd>…\u003C\u002Fdd>\u003C\u002Fdl>"," —\nstructurally correct.",[10,975,977],{"id":976},"no-id-in-the-data","No ID in the data?",[15,979,980],{},"Generate IDs when the data enters the app, not at render time:",[24,982,984],{"className":26,"code":983,"language":28,"meta":29,"style":29},"\u002F\u002F When you receive data (e.g., in a reducer or fetch handler)\nconst items = rawItems.map(item => ({\n  ...item,\n  id: crypto.randomUUID(),   \u002F\u002F stable across renders — generated once\n}))\n",[19,985,986,991,1014,1022,1036],{"__ignoreMap":29},[33,987,988],{"class":35,"line":36},[33,989,990],{"class":251},"\u002F\u002F When you receive data (e.g., in a reducer or fetch handler)\n",[33,992,993,995,998,1000,1003,1005,1007,1009,1011],{"class":35,"line":58},[33,994,614],{"class":39},[33,996,997],{"class":283}," items",[33,999,620],{"class":39},[33,1001,1002],{"class":47}," rawItems.",[33,1004,86],{"class":43},[33,1006,89],{"class":47},[33,1008,720],{"class":51},[33,1010,95],{"class":39},[33,1012,1013],{"class":47}," ({\n",[33,1015,1016,1019],{"class":35,"line":67},[33,1017,1018],{"class":39},"  ...",[33,1020,1021],{"class":47},"item,\n",[33,1023,1024,1027,1030,1033],{"class":35,"line":80},[33,1025,1026],{"class":47},"  id: crypto.",[33,1028,1029],{"class":43},"randomUUID",[33,1031,1032],{"class":47},"(),   ",[33,1034,1035],{"class":251},"\u002F\u002F stable across renders — generated once\n",[33,1037,1038],{"class":35,"line":100},[33,1039,1040],{"class":47},"}))\n",[15,1042,1043],{},"Or use a composite key from fields that together are unique within the list:",[24,1045,1047],{"className":26,"code":1046,"language":28,"meta":29,"style":29},"{countries.map(c => (\n  \u003CCountryRow key={`${c.code}-${c.region}`} country={c} \u002F>\n))}\n",[19,1048,1049,1065,1108],{"__ignoreMap":29},[33,1050,1051,1054,1056,1058,1061,1063],{"class":35,"line":36},[33,1052,1053],{"class":47},"{countries.",[33,1055,86],{"class":43},[33,1057,89],{"class":47},[33,1059,1060],{"class":51},"c",[33,1062,95],{"class":39},[33,1064,64],{"class":47},[33,1066,1067,1069,1072,1074,1076,1078,1080,1082,1084,1086,1088,1090,1092,1095,1097,1100,1103,1105],{"class":35,"line":58},[33,1068,729],{"class":47},[33,1070,1071],{"class":283},"CountryRow",[33,1073,109],{"class":43},[33,1075,112],{"class":39},[33,1077,473],{"class":47},[33,1079,477],{"class":476},[33,1081,1060],{"class":47},[33,1083,325],{"class":476},[33,1085,19],{"class":47},[33,1087,488],{"class":476},[33,1089,1060],{"class":47},[33,1091,325],{"class":476},[33,1093,1094],{"class":47},"region",[33,1096,499],{"class":476},[33,1098,1099],{"class":47},"} ",[33,1101,1102],{"class":43},"country",[33,1104,112],{"class":39},[33,1106,1107],{"class":47},"{c} \u002F>\n",[33,1109,1110],{"class":35,"line":67},[33,1111,751],{"class":47},[10,1113,1115],{"id":1114},"handling-dynamic-list-types","Handling dynamic list types",[15,1117,1118],{},"When a list can contain items of different component types, use an object map\nto select the component:",[24,1120,1122],{"className":26,"code":1121,"language":28,"meta":29,"style":29},"const BLOCK_MAP = {\n  text:    TextBlock,\n  image:   ImageBlock,\n  code:    CodeBlock,\n  divider: DividerBlock,\n}\n\nfunction ContentArea({ blocks }) {\n  return (\n    \u003C>\n      {blocks.map(block => {\n        const Block = BLOCK_MAP[block.type]\n        if (!Block) return null\n        return \u003CBlock key={block.id} {...block} \u002F>\n      })}\n    \u003C\u002F>\n  )\n}\n",[19,1123,1124,1136,1141,1146,1151,1156,1160,1164,1178,1184,1189,1205,1220,1240,1263,1269,1275,1280],{"__ignoreMap":29},[33,1125,1126,1128,1131,1133],{"class":35,"line":36},[33,1127,614],{"class":39},[33,1129,1130],{"class":283}," BLOCK_MAP",[33,1132,620],{"class":39},[33,1134,1135],{"class":47}," {\n",[33,1137,1138],{"class":35,"line":58},[33,1139,1140],{"class":47},"  text:    TextBlock,\n",[33,1142,1143],{"class":35,"line":67},[33,1144,1145],{"class":47},"  image:   ImageBlock,\n",[33,1147,1148],{"class":35,"line":80},[33,1149,1150],{"class":47},"  code:    CodeBlock,\n",[33,1152,1153],{"class":35,"line":100},[33,1154,1155],{"class":47},"  divider: DividerBlock,\n",[33,1157,1158],{"class":35,"line":118},[33,1159,170],{"class":47},[33,1161,1162],{"class":35,"line":135},[33,1163,431],{"emptyLinePlaceholder":430},[33,1165,1166,1168,1171,1173,1176],{"class":35,"line":145},[33,1167,40],{"class":39},[33,1169,1170],{"class":43}," ContentArea",[33,1172,48],{"class":47},[33,1174,1175],{"class":51},"blocks",[33,1177,55],{"class":47},[33,1179,1180,1182],{"class":35,"line":151},[33,1181,61],{"class":39},[33,1183,64],{"class":47},[33,1185,1186],{"class":35,"line":161},[33,1187,1188],{"class":47},"    \u003C>\n",[33,1190,1191,1194,1196,1198,1201,1203],{"class":35,"line":167},[33,1192,1193],{"class":47},"      {blocks.",[33,1195,86],{"class":43},[33,1197,89],{"class":47},[33,1199,1200],{"class":51},"block",[33,1202,95],{"class":39},[33,1204,1135],{"class":47},[33,1206,1207,1210,1213,1215,1217],{"class":35,"line":534},[33,1208,1209],{"class":39},"        const",[33,1211,1212],{"class":283}," Block",[33,1214,620],{"class":39},[33,1216,1130],{"class":283},[33,1218,1219],{"class":47},"[block.type]\n",[33,1221,1222,1225,1228,1231,1234,1237],{"class":35,"line":539},[33,1223,1224],{"class":39},"        if",[33,1226,1227],{"class":47}," (",[33,1229,1230],{"class":39},"!",[33,1232,1233],{"class":47},"Block) ",[33,1235,1236],{"class":39},"return",[33,1238,1239],{"class":283}," null\n",[33,1241,1242,1245,1247,1250,1252,1254,1257,1260],{"class":35,"line":545},[33,1243,1244],{"class":39},"        return",[33,1246,280],{"class":47},[33,1248,1249],{"class":283},"Block",[33,1251,109],{"class":43},[33,1253,112],{"class":39},[33,1255,1256],{"class":47},"{block.id} {",[33,1258,1259],{"class":39},"...",[33,1261,1262],{"class":47},"block} \u002F>\n",[33,1264,1266],{"class":35,"line":1265},15,[33,1267,1268],{"class":47},"      })}\n",[33,1270,1272],{"class":35,"line":1271},16,[33,1273,1274],{"class":47},"    \u003C\u002F>\n",[33,1276,1278],{"class":35,"line":1277},17,[33,1279,164],{"class":47},[33,1281,1283],{"class":35,"line":1282},18,[33,1284,170],{"class":47},[15,1286,1287,1288,1290],{},"Note: ",[19,1289,1249],{}," must be uppercase. JSX treats a lowercase tag as a DOM element\nstring; it treats an uppercase name as a JavaScript variable reference.",[10,1292,1294],{"id":1293},"nested-lists","Nested lists",[15,1296,1297,1298,1300,1301,325],{},"Each nesting level is its own sibling context. Keys at one level don't interact\nwith keys at another level. Every ",[19,1299,176],{}," at every level needs its own ",[19,1302,180],{},[24,1304,1306],{"className":26,"code":1305,"language":28,"meta":29,"style":29},"function Table({ rows }) {\n  return (\n    \u003Ctable>\n      \u003Ctbody>\n        {rows.map(row => (\n          \u003Ctr key={row.id}>\n            {row.cells.map(cell => (\n              \u003Ctd key={cell.colId}>{cell.value}\u003C\u002Ftd>\n            ))}\n          \u003C\u002Ftr>\n        ))}\n      \u003C\u002Ftbody>\n    \u003C\u002Ftable>\n  )\n}\n",[19,1307,1308,1322,1328,1337,1347,1362,1376,1392,1411,1416,1425,1430,1439,1447,1451],{"__ignoreMap":29},[33,1309,1310,1312,1315,1317,1320],{"class":35,"line":36},[33,1311,40],{"class":39},[33,1313,1314],{"class":43}," Table",[33,1316,48],{"class":47},[33,1318,1319],{"class":51},"rows",[33,1321,55],{"class":47},[33,1323,1324,1326],{"class":35,"line":58},[33,1325,61],{"class":39},[33,1327,64],{"class":47},[33,1329,1330,1332,1335],{"class":35,"line":67},[33,1331,70],{"class":47},[33,1333,1334],{"class":73},"table",[33,1336,77],{"class":47},[33,1338,1339,1342,1345],{"class":35,"line":80},[33,1340,1341],{"class":47},"      \u003C",[33,1343,1344],{"class":73},"tbody",[33,1346,77],{"class":47},[33,1348,1349,1352,1354,1356,1358,1360],{"class":35,"line":100},[33,1350,1351],{"class":47},"        {rows.",[33,1353,86],{"class":43},[33,1355,89],{"class":47},[33,1357,480],{"class":51},[33,1359,95],{"class":39},[33,1361,64],{"class":47},[33,1363,1364,1366,1369,1371,1373],{"class":35,"line":118},[33,1365,121],{"class":47},[33,1367,1368],{"class":73},"tr",[33,1370,109],{"class":43},[33,1372,112],{"class":39},[33,1374,1375],{"class":47},"{row.id}>\n",[33,1377,1378,1381,1383,1385,1388,1390],{"class":35,"line":135},[33,1379,1380],{"class":47},"            {row.cells.",[33,1382,86],{"class":43},[33,1384,89],{"class":47},[33,1386,1387],{"class":51},"cell",[33,1389,95],{"class":39},[33,1391,64],{"class":47},[33,1393,1394,1397,1400,1402,1404,1407,1409],{"class":35,"line":145},[33,1395,1396],{"class":47},"              \u003C",[33,1398,1399],{"class":73},"td",[33,1401,109],{"class":43},[33,1403,112],{"class":39},[33,1405,1406],{"class":47},"{cell.colId}>{cell.value}\u003C\u002F",[33,1408,1399],{"class":73},[33,1410,77],{"class":47},[33,1412,1413],{"class":35,"line":151},[33,1414,1415],{"class":47},"            ))}\n",[33,1417,1418,1421,1423],{"class":35,"line":161},[33,1419,1420],{"class":47},"          \u003C\u002F",[33,1422,1368],{"class":73},[33,1424,77],{"class":47},[33,1426,1427],{"class":35,"line":167},[33,1428,1429],{"class":47},"        ))}\n",[33,1431,1432,1435,1437],{"class":35,"line":534},[33,1433,1434],{"class":47},"      \u003C\u002F",[33,1436,1344],{"class":73},[33,1438,77],{"class":47},[33,1440,1441,1443,1445],{"class":35,"line":539},[33,1442,154],{"class":47},[33,1444,1334],{"class":73},[33,1446,77],{"class":47},[33,1448,1449],{"class":35,"line":545},[33,1450,164],{"class":47},[33,1452,1453],{"class":35,"line":1265},[33,1454,170],{"class":47},[15,1456,1457,1460,1461,1464],{},[19,1458,1459],{},"row.id"," and ",[19,1462,1463],{},"cell.colId"," are scoped to their own lists. No namespace collision.",[10,1466,1468],{"id":1467},"reconciliation-deep-dive","Reconciliation deep dive",[15,1470,1471],{},"Here's what React does internally when a list updates:",[24,1473,1478],{"className":1474,"code":1476,"language":1477},[1475],"language-text","Before: [Apple(key=1), Banana(key=2), Cherry(key=3)]\nAfter:  [Cherry(key=3), Apple(key=1), Banana(key=2)]\n\nWith stable keys:\n  React maps old keys: {1: Apple-fiber, 2: Banana-fiber, 3: Cherry-fiber}\n  For new key=3 at index 0: fiber exists → move Cherry's DOM node to index 0\n  For new key=1 at index 1: fiber exists → move Apple's DOM node to index 1\n  For new key=2 at index 2: fiber exists → move Banana's DOM node to index 2\n  Result: 3 DOM moves, 0 unmounts, 0 mounts\n\nWithout keys (positional):\n  Index 0: Apple → Cherry. React updates props. 1 update.\n  Index 1: Banana → Apple. React updates props. 1 update.\n  Index 2: Cherry → Banana. React updates props. 1 update.\n  Result: 3 prop updates — correct for display, but state stays at old position.\n","text",[19,1479,1476],{"__ignoreMap":29},[15,1481,1482],{},"Keys make reordering O(n) and correct. Without them, reordering is O(n) in\nmutations but incorrect for stateful components.",[10,1484,1486],{"id":1485},"what-interviewers-are-testing","What interviewers are testing",[15,1488,1489],{},"Keys questions check whether you understand:",[381,1491,1492,1502,1505,1508,1511],{},[106,1493,1494,1497,1498,1501],{},[124,1495,1496],{},"Why"," keys are required, not just ",[124,1499,1500],{},"that"," they are required.",[106,1503,1504],{},"The correctness bug with index keys on mutable lists.",[106,1506,1507],{},"What makes a key \"good\" (unique among siblings, stable, never generated at\nrender time).",[106,1509,1510],{},"Where to place the key (outermost element of the map callback).",[106,1512,1513,1514,1516],{},"The ",[19,1515,895],{}," keying pattern for multi-element list items.",[15,1518,1519],{},"The follow-up question is almost always the index bug scenario. Be ready to\ndescribe exactly what goes wrong with a concrete example — state staying at\nthe wrong position while props update.",[1521,1522,1523],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":29,"searchDepth":58,"depth":58,"links":1525},[1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537],{"id":12,"depth":58,"text":13},{"id":184,"depth":58,"text":185},{"id":230,"depth":58,"text":231},{"id":378,"depth":58,"text":379},{"id":573,"depth":58,"text":574},{"id":685,"depth":58,"text":686},{"id":823,"depth":58,"text":824},{"id":976,"depth":58,"text":977},{"id":1114,"depth":58,"text":1115},{"id":1293,"depth":58,"text":1294},{"id":1467,"depth":58,"text":1468},{"id":1485,"depth":58,"text":1486},"React lists and keys interview questions — key prop, reconciliation, index as key pitfalls, stable keys, Fragment in lists, and rendering nested arrays.","easy","md","React","react",{"subtopicSlug":1544},"lists-keys","\u002Fblog\u002Freact-lists-keys-guide","\u002Freact\u002Fcomponents\u002Flists-keys",{"title":5,"description":1538},"blog\u002Freact-lists-keys-guide","Lists and Keys","Components","components","2026-06-23","_Apb-mS5O4KQZBGsoHm-tLPb2ziVlAqfo6sa2oAMmv8",1782244083412]