[{"data":1,"prerenderedAt":257},["ShallowReactive",2],{"article-react-list-keys":3,"related-articles":155},{"id":4,"title":5,"body":6,"categoryLabel":139,"categorySlug":140,"description":141,"extension":142,"featured":143,"meta":144,"navigation":145,"path":146,"publishedAt":147,"readingMinutes":148,"seo":149,"stem":150,"tags":151,"__hash__":154},"blog\u002Fblog\u002Freact-list-keys.md","React 列表渲染里的 key 有什么用",{"type":7,"value":8,"toc":135},"minimark",[9,22,26,112,119,122,125,131],[10,11,12,13,17,18,21],"p",{},"用 ",[14,15,16],"code",{},"map"," 渲染数组时，React 要知道每一项在更新前后是否还是同一个项目。",[14,19,20],{},"key"," 就是列表项的稳定标识。",[23,24,25],"h2",{"id":25},"使用数据本身的标识",[27,28,33],"pre",{"className":29,"code":30,"language":31,"meta":32,"style":32},"language-tsx shiki shiki-themes github-light-high-contrast","{tasks.map((task) => (\n  \u003Cli key={task.id}>{task.title}\u003C\u002Fli>\n))}\n","tsx","",[14,34,35,64,106],{"__ignoreMap":32},[36,37,40,44,47,50,54,57,61],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sigWx","{tasks.",[36,45,16],{"class":46},"s3dhs",[36,48,49],{"class":42},"((",[36,51,53],{"class":52},"sV4o_","task",[36,55,56],{"class":42},") ",[36,58,60],{"class":59},"sTJeM","=>",[36,62,63],{"class":42}," (\n",[36,65,67,70,74,78,81,84,87,90,93,96,98,101,103],{"class":38,"line":66},2,[36,68,69],{"class":42},"  \u003C",[36,71,73],{"class":72},"s742_","li",[36,75,77],{"class":76},"sacAq"," key",[36,79,80],{"class":59},"={",[36,82,83],{"class":42},"task.id",[36,85,86],{"class":59},"}",[36,88,89],{"class":42},">",[36,91,92],{"class":59},"{",[36,94,95],{"class":42},"task.title",[36,97,86],{"class":59},[36,99,100],{"class":42},"\u003C\u002F",[36,102,73],{"class":72},[36,104,105],{"class":42},">\n",[36,107,109],{"class":38,"line":108},3,[36,110,111],{"class":42},"))}\n",[10,113,114,115,118],{},"如果数据里有稳定且唯一的 ",[14,116,117],{},"id","，优先使用它。插入、删除或重新排序后，React 就能更准确地对应列表项。",[23,120,121],{"id":121},"为什么通常不选数组下标",[10,123,124],{},"数组下标表达的是当前位置。当列表顺序变化时，同一个下标可能对应另一条数据，输入框等带状态的内容就可能跟着错位。",[10,126,127,128,130],{},"静态、永不改变顺序的列表用下标通常不会出问题；可变列表应尽量使用稳定标识。",[14,129,20],{}," 也只供 React 使用，不会作为普通 Props 传到组件里。",[132,133,134],"style",{},"html pre.shiki code .sigWx, html code.shiki .sigWx{--shiki-default:#0E1116}html pre.shiki code .s3dhs, html code.shiki .s3dhs{--shiki-default:#622CBC}html pre.shiki code .sV4o_, html code.shiki .sV4o_{--shiki-default:#702C00}html pre.shiki code .sTJeM, html code.shiki .sTJeM{--shiki-default:#A0111F}html pre.shiki code .s742_, html code.shiki .s742_{--shiki-default:#024C1A}html pre.shiki code .sacAq, html code.shiki .sacAq{--shiki-default:#023B95}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);}",{"title":32,"searchDepth":66,"depth":66,"links":136},[137,138],{"id":25,"depth":66,"text":25},{"id":121,"depth":66,"text":121},"React","react","通过稳定的 key 帮助 React 识别列表项目，避免用数组下标造成的状态错位。","md",false,{},true,"\u002Fblog\u002Freact-list-keys","2026-08-12",4,{"title":5,"description":141},"blog\u002Freact-list-keys",[139,152,153],"列表","学习笔记","eLZbCgsAOwfr8qMV0eR2tU8cAwf5mhd0Epvjm7-9-nw",[156,168,178,187,189,197,205,213,221,231,239,247],{"id":157,"path":158,"title":159,"description":160,"categorySlug":161,"categoryLabel":162,"publishedAt":163,"readingMinutes":148,"featured":145,"tags":164},"blog\u002Fblog\u002Fcss-grid-cards.md","\u002Fblog\u002Fcss-grid-cards","用 CSS Grid 排列自适应卡片","使用 repeat、minmax 和 auto-fit，让卡片列数随容器宽度自然变化。","styles","页面与样式","2026-09-10",[165,166,167],"CSS","Grid","页面布局",{"id":169,"path":170,"title":171,"description":172,"categorySlug":161,"categoryLabel":162,"publishedAt":173,"readingMinutes":174,"featured":143,"tags":175},"blog\u002Fblog\u002Fmobile-layout-checklist.md","\u002Fblog\u002Fmobile-layout-checklist","做移动端页面适配时的检查笔记","从内容宽度、触控区域、文字换行和键盘焦点几个方面检查窄屏体验。","2026-08-20",5,[165,176,177],"响应式","可访问性",{"id":179,"path":180,"title":181,"description":182,"categorySlug":140,"categoryLabel":139,"publishedAt":183,"readingMinutes":184,"featured":145,"tags":185},"blog\u002Fblog\u002Freact-controlled-form.md","\u002Fblog\u002Freact-controlled-form","React 受控表单：从一个输入框开始","用一个简单的姓名输入框，理解 value、onChange 与 React state 之间的关系。","2026-09-18",6,[139,186,153],"表单",{"id":4,"path":146,"title":5,"description":141,"categorySlug":140,"categoryLabel":139,"publishedAt":147,"readingMinutes":148,"featured":143,"tags":188},[139,152,153],{"id":190,"path":191,"title":192,"description":193,"categorySlug":140,"categoryLabel":139,"publishedAt":194,"readingMinutes":174,"featured":143,"tags":195},"blog\u002Fblog\u002Freact-props-and-state.md","\u002Fblog\u002Freact-props-and-state","React 组件里的 Props 和 State","用一个简单的信息卡片区分外部传入的数据和组件内部会变化的数据。","2026-08-28",[139,196,153],"组件",{"id":198,"path":199,"title":200,"description":201,"categorySlug":140,"categoryLabel":139,"publishedAt":202,"readingMinutes":174,"featured":143,"tags":203},"blog\u002Fblog\u002Freact-small-components.md","\u002Fblog\u002Freact-small-components","把重复的界面拆成小组件","从重复的按钮和卡片开始，认识组件拆分的几个简单信号。","2026-07-16",[139,196,204],"练习记录",{"id":206,"path":207,"title":208,"description":209,"categorySlug":140,"categoryLabel":139,"publishedAt":210,"readingMinutes":184,"featured":143,"tags":211},"blog\u002Fblog\u002Freact-use-effect-notes.md","\u002Fblog\u002Freact-use-effect-notes","React useEffect 的依赖和清理","整理 useEffect 何时运行，以及订阅和定时器为什么需要清理。","2026-06-30",[139,212,153],"useEffect",{"id":214,"path":215,"title":216,"description":217,"categorySlug":140,"categoryLabel":139,"publishedAt":218,"readingMinutes":148,"featured":143,"tags":219},"blog\u002Fblog\u002Freact-use-state-practice.md","\u002Fblog\u002Freact-use-state-practice","用 useState 管理一个简单的计数交互","从加一和重置两个操作，熟悉 React state 的声明与更新方式。","2026-07-30",[139,220,204],"useState",{"id":222,"path":223,"title":224,"description":225,"categorySlug":226,"categoryLabel":227,"publishedAt":228,"readingMinutes":174,"featured":145,"tags":229},"blog\u002Fblog\u002Ftypescript-component-props.md","\u002Fblog\u002Ftypescript-component-props","给 React 组件的 Props 添加 TypeScript 类型","用必填属性和可选属性描述组件接口，让使用方式在编辑器里更清晰。","typescript","TypeScript","2026-09-02",[227,139,230],"类型",{"id":232,"path":233,"title":234,"description":235,"categorySlug":226,"categoryLabel":227,"publishedAt":236,"readingMinutes":174,"featured":145,"tags":237},"blog\u002Fblog\u002Ftypescript-narrowing.md","\u002Fblog\u002Ftypescript-narrowing","TypeScript 类型收窄入门","使用 typeof 和条件判断缩小联合类型的范围，让后续代码更安全。","2026-09-25",[227,238,153],"类型收窄",{"id":240,"path":241,"title":242,"description":243,"categorySlug":226,"categoryLabel":227,"publishedAt":244,"readingMinutes":148,"featured":143,"tags":245},"blog\u002Fblog\u002Ftypescript-union-status.md","\u002Fblog\u002Ftypescript-union-status","用联合类型描述请求状态","把加载、成功和失败等状态限制在明确的集合里，减少拼写错误和遗漏分支。","2026-08-04",[227,246,153],"联合类型",{"id":248,"path":249,"title":250,"description":251,"categorySlug":252,"categoryLabel":253,"publishedAt":254,"readingMinutes":148,"featured":143,"tags":255},"blog\u002Fblog\u002Fvite-react-project.md","\u002Fblog\u002Fvite-react-project","用 Vite 创建一个 React + TypeScript 小项目","记录从初始化模板到启动开发服务器的基础步骤，以及几个值得先检查的文件。","tools","开发工具","2026-06-12",[256,139,227],"Vite",1792674168122]