为何 React JSX 循环需要使用 key

key 是 React 用于识别列表中哪些子元素被改变、添加或删除的唯一标识符
它帮助 React 更高效、更准确地更新和重新渲染列表

1、核心原因:Diff算法与性能优化

React 的核心思想之一是通过虚拟 DOM (Virtual DOM) 来减少对真实 DOM 的直接操作,从而提升性能。当组件的状态或属性发生变化时,React 会创建一个新的虚拟 DOM 树,并将其与之前的虚拟 DOM 树进行比较。这个过程叫做 “Diffing”(差异比对)

假设:在处理列表时候,没有key(React的diffing 算法会变更很低效),默认索引为key作为标识,
原本有一个列表[‘A’,‘B’,‘C’,‘D’],现在需要再原来的基础上在开头新增一个元素 变为 [‘E’,‘A’,‘B’,‘C’,‘D’]

如没有key:
在这里插入图片描述
React 会比较第一个位置的 A 和 X,发现内容变了,于是更新第一个

  • 的文本。接着比较第二个位置的 B 和 A,又更新…以此类推。它会修改所有已有的子元素,而不是意识到 A, B, C, D 只是位置后移了,最终还会在末尾创建一个新的
  • 。这导致了大量不必要的真实 DOM 操作(更新),性能极差
  • 有key时:
    在这里插入图片描述

    React 通过 key(例如 key={item.id})知道 A, B, C ,D 仍然是原来的项,只是移动了位置。它只会创建一个新的

  • (对应 X)并插入到开头,然后移动原有的三个
  • 。这个过程(移动和插入)远比更新每个节点的内容要高效。
  • 2、保持状态的正确性(这是更重要的原因!)
    key 不仅仅是性能优化,它直接关系到组件实例状态的正确性。

    React 使用 key 来匹配多次渲染间的组件实例。如果 key 保持不变,React 会认为这是同一个组件实例,因此它会保留该组件的状态(如 useState、useRef 的值)。如果 key 改变了,React 会销毁旧的组件实例并创建一个新的

    看一个经典的例子:一个待办事项列表,每个事项有一个输入框可以编辑。

    // 错误的做法:使用 index 作为 key
    const TodoList = () => {const [todos, setTodos] = useState(['Learn React', 'Build a project']);const addTodo = () => {const newTodo = prompt('New todo:');// 在列表开头添加新项setTodos([newTodo, ...todos]);};return (<div><button onClick={addTodo}>Add Todo</button><ul>{todos.map((todo, index) => (// 🚨 危险!使用 index 作为 key<li key={index}>{todo}<input type="text" placeholder="Edit..." /></li>))}</ul></div>);
    };
    

    会发生什么?

    初始有两个待办项:Learn React 和 Build a project。它们的 key 分别是 0 和 1。

    你在 第二项 (key=1) 的输入框里输入了 “test”。

    你点击 “Add Todo”,在开头添加了一个新项 “New Item”。

    现在列表变成了:[‘New Item’, ‘Learn React’, ‘Build a project’]。

    React 开始 Diffing:

    旧 key=0 (‘Learn React’) vs 新 key=0 (‘New Item’) -> 内容变了,更新文本,但输入框实例被复用。

    旧 key=1 (‘Build a project’) vs 新 key=1 (‘Learn React’) -> 内容变了,更新文本,输入框实例被复用(现在它显示之前输入的 “test”!)。

    创建一个新的 key=2 的项 (‘Build a project’)。

    结果:你原本在第二项输入的 “test”,神奇地“跳”到了现在第二项(‘Learn React’)的输入框里!这显然不是用户想要的行为。

    如何修复?

    // 正确的做法:使用唯一的 id 作为 key
    {todos.map((todo) => (<li key={todo.id}> {/* 假设每个 todo 对象都有唯一的 id */}{todo.text}<input type="text" placeholder="Edit..." /></li>
    ))}
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95494.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jetson AGX Orin平台R36.3.0版本1080P25fps MIPI相机图像采集行缺失调试记录

1.前言 主板:AGX Orin 官方开发套件 开发版本: R36.3.0版本 相机参数如下: 相机硬件接口: 2. 梳理大致开发流程 核对线序/定制相机转接板 编写camera driver驱动 编写camera dts配置文件 调camera参数/测试出图 前期基本流程就不多介绍了直接讲正题 3. 问题描述 …

力扣hot100:螺旋矩阵(边界压缩,方向模拟)(54)

在解决螺旋矩阵问题时&#xff0c;我们需要按照顺时针螺旋顺序遍历矩阵&#xff0c;并返回所有元素。本文将分享两种高效的解决方案&#xff1a;边界收缩法和方向模拟法。题目描述边界收缩法边界收缩法通过定义四个边界&#xff08;上、下、左、右&#xff09;来模拟螺旋遍历的…

[嵌入式embed][Qt]Qt5.12+Opencv4.x+Cmake4.x_用Qt编译linux-Opencv库 测试

[嵌入式embed][Qt]Qt5.12Opencv4.xCmake4.x_用Qt编译linux-Opencv库 & 测试前文:准备环境安装qt-opencv必备库git-clone opencv库编译opencv库特殊:opencv编译的include,编译出来后多嵌套了一层文件夹,手工处理下改为include/opencv2测试demo新建项目QOpencv3.promain.cpp百…

百度智能云「智能集锦」自动生成短剧解说,三步实现专业级素材生产

备受剪辑压力困扰的各位自媒体老板、MCN 同学们、投放平台大佬们&#xff0c;解放双手和大脑的好机会它来了&#xff01; 在这个数字化飞速发展的时代&#xff0c;智能技术正以前所未有的速度改变着我们的生活与工作方式。百度智能云&#xff0c;作为智能科技的引领者&#xf…

FPGA笔试面试常考问题及答案汇总

经历了无数的笔试面试之后&#xff0c;不知道大家有没有发现FPGA的笔试面试还是有很多共通之处和规律可循的。所以一定要掌握笔试面试常考的问题。FPGA设计方向&#xff08;部分题目&#xff09;1. 什么是同步逻辑和异步逻辑&#xff1f;同步逻辑 是指在同一个时钟信号的控制下…

从0开始的github学生认证并使用copilot教程(超详细!)

目录 一.注册github账号 1.1、仅仅是注册 1.2、完善你的profile 二、Github 学生认证 邮箱 学校名称 How do you plan to use Github? Upload Proof 学校具体信息 一.注册github账号 1.1、仅仅是注册 1.用如QQ邮箱的第三方邮箱注册github 再添加.edu结尾的教育邮箱&…

自动驾驶叉车与 WMS 集成技术方案:数据交互、协议适配与系统对接实现

自动驾驶叉车与仓库管理系统&#xff08;WMS&#xff09;是现代物流自动化的核心。当这两项技术协同工作时&#xff0c;仓库将实现前所未有的效率、准确性和可扩展性。以下是利用其集成实现最佳效果的方法。 为何集成至关重要 仓库管理在当今运营中扮演着至关重要的角色&…

“企业版维基百科”Confluence

“企业版维基百科”Confluence Confluence 是一款由澳大利亚公司 Atlassian 开发的企业级团队协作与知识管理软件。您可以把它理解为一个功能非常强大的 “企业版维基百科” 或 “团队知识库”。 它的核心目标是帮助团队在一个统一的平台上创建、共享、组织和讨论项目文档、会议…

QT去除显示的红色和黄色下划线的办法

在使用 Qt Creator 开发项目时,有时候会遇到这样的情况: 代码明明没有错误,但编辑器里却出现了红色或黄色的下划线提示,甚至让人误以为代码有问题。其实,这通常是 Qt Creator 的代码模型没有及时更新 导致的,而不是项目本身的错误。 为什么会出现红色和黄色下划线? 红…

域内的权限提升

CVE-2020-1472域内有一个服务&#xff1a;MS-NRPC&#xff08;建立与域控安全通道&#xff09;&#xff0c;可利用此漏洞获取域管访问权限。检测这个漏洞能不能打&#xff0c;能打之后&#xff0c;将域控的机器hash置空&#xff0c;密码为空&#xff0c;那么你就可以通过空的ha…

一键掌握服务器健康状态与安全风险

一键掌握服务器健康状态与安全风险 在服务器运维工作中,定期对系统进行全面检查是保障服务稳定运行的关键环节。手动检查不仅耗时费力,还容易遗漏关键指标。今天我将为大家介绍一款功能全面的系统综合巡检工具,只需一键运行,即可完成系统状态、性能、安全等多维度检查,并…

线性代数第一讲—向量组

文章目录考纲术语向量组的线性表示与线性相关判别线性相关性的七大定理极大线性无关组、等价向量组、向量组的秩等价矩阵和等价向量组向量空间基本概念基变换、坐标变换 考纲术语 n维向量n维行向量n维列向量分量向量相等向量的加法向量的数乘向量的内积正交向量的模单位向量标准…

涉私数据安全与可控匿名化利用机制研究(下)

文章目录前言三、可信数据空间支撑可控匿名化机制&#xff08;一&#xff09;基于政府可信根的可控匿名化&#xff08;二&#xff09;可信数据空间“中国模式”保障数据全生命周期合规可控&#xff08;三&#xff09;可控匿名化对大模型数据可逆风险的防御机制前言 尽管《个人…

More Effective C++ 条款25:将构造函数和非成员函数虚拟化

More Effective C 条款25&#xff1a;将构造函数和非成员函数虚拟化核心思想&#xff1a;通过虚拟构造函数和非成员函数&#xff0c;实现运行时的多态行为&#xff0c;允许在不知道对象具体类型的情况下创建新对象或执行操作&#xff0c;增强代码的灵活性和扩展性。 &#x1f6…

血缘元数据采集开放标准:OpenLineage Guides 在 Airflow 中使用 OpenLineage Proxy

OpenLineage 是一个用于元数据和血缘采集的开放标准&#xff0c;专为在作业运行时动态采集数据而设计。它通过统一的命名策略定义了由作业&#xff08;Job&#xff09;、运行实例&#xff08;Run&#xff09;和数据集&#xff08;Dataset&#xff09; 组成的通用模型&#xff0…

【Linux】网络(中)

目录1. 序列化和反序列化1.1 序列化1.2 反序列化2. 网络版本计算器&#xff08;自定义协议&#xff09;3. 再次理解OSI七层模型4. HTTP协议4.1 HTTP协议格式4.2 HTTP的方法4.3 HTTP的状态码4.4 HTTP常见Header4.5 长连接和短连接4.6 Cookie5. HTTPS协议5.1 对称加密和非对称加密…

AI 写作实战:用 GPT-4o+ Claude 3 生成小红书文案,转化率提升 30%

引言・AI 写作开启小红书营销新引擎在社交媒体营销的浪潮中&#xff0c;小红书以其独特的社区氛围和庞大的年轻用户群体&#xff0c;成为品牌推广的关键阵地。然而&#xff0c;撰写既吸引眼球又能高效转化的文案并非易事&#xff0c;传统人工编写不仅耗时费力&#xff0c;还难以…

一个月涨粉30万,Coze智能体一键生成民间传说爆款视频,3分钟上手

最近发现一个账号&#xff0c;用AI将民间传说故事转化为生动视频&#xff0c;短短一个月涨粉30万&#xff0c;条均播放 量破百万。这种视频制作真的需要专业团队吗&#xff1f;今天教大家用Coze智能体工作流&#xff0c;一键生成 爆款民间故事视频&#xff01;工作流功能 用Coz…

Linux arm64 PTE contiguous bit

文章目录一、简介1.1 contiguous PTE1.2 demo二、Linux 内核中的实现2.1 宏定义2.2 __create_pgd_mapping2.2.1 alloc_init_cont_pmdinit_pmd2.2.2 alloc_init_cont_pteinit_pte2.3 hugetlbpage2.3.1 find_num_contig2.3.2 num_contig_ptes2.3.3 huge_pte_offset2.3.4 huge_pte…

深入分析 json2(新)与标准的 jsonrpc的区别

这两个模块都用于实现 JSON 风格的远程过程调用&#xff08;RPC&#xff09;接口&#xff0c;但设计哲学、使用方式、安全性和现代化程度有显著差异。 &#x1f4c2; 对比背景 文件 功能 来源 jsonrpc.py 标准的 JSON-RPC 2.0 兼容接口 Odoo 内核已有逻辑 json2.py 自定…