为什么 React JS 不自动为动态子项生成键?

2024-05-04

在编写 ReactJS 代码时,我必须为动态子项提供键。例如:

render() {
  const {options} = this.state
  const availableOptions = options.map(opt => {
    return (
      <option key={opt.id} value={opt.id}>{opt.displayValue}</option>}
    )
  }

  return (
    <select onChange={this._onOptionSelect}>
      {availableOptions}
    </select>
  )
}

我明白为什么钥匙在那里。但为什么要I必须给他们吗?无法做出反应,只分配一个运行号或 UUIDv4 或其他东西?

相关文档:http://facebook.github.io/react/docs/multiple-components.html#dynamic-children http://facebook.github.io/react/docs/multiple-components.html#dynamic-children


Tl;dr

您需要为与该元素关联的动态元素分配一个唯一的键data(可能是数据库字段中的 ID 或其他内容)因为它会停止不必要的重新渲染。这是 React 的主要吸引力,也是它以其性能而闻名的原因。

Reason

您需要为动态子项分配一个唯一的键,因为这就是 React 的方式虚拟DOM http://facebook.github.io/react/docs/advanced-performance.html将该元素与specific一条数据。我认为一个例子有助于说明。

假设您有一个包含 1,000 个动态生成的项目的列表。你could只需使用index参数是从传入的map函数动态地为这些项目分配一个键。但是,如果您想更改这些项目的顺序(也许按字母顺序排序)怎么办?因为key这些项目并不绑定到特定的数据,而是动态生成的,React 虚拟 DOM 无法跟踪这些元素。这意味着它必须重新渲染all1,000 个元素只是为了更改排序。但是,假设每个项目都分配了一个从数据库填充的唯一 ID。虚拟 DOM 足够聪明,可以看到即使元素的顺序发生了变化,元素本身的数据仍然是相同的。因此,它会重新渲染none元素的顺序,尽管它们的顺序发生了变化。

如果其中任何一个不清楚,那么一旦您剖析了虚拟 DOM 的实际工作原理,就会完全明白了。本质上,虚拟 DOM 是实际 DOM 的副本。 React 会比较两者,并且仅重新渲染实际更改的内容。这就是 React 获得速度的地方。假设您有 3 个动态列表<Item />组件,并且您还动态生成它们的密钥。

<Item key="1">Banana</Item>
<Item key="2">Orange</Item>
<Item key="3">Apple</Item>

现在,如果您按字母顺序重新排序这些项目,它们的键也将动态重新分配。

<Item key="1">Apple</Item>
<Item key="2">Banana</Item>
<Item key="3">Orange</Item>

此时,React 会比较键 1 的内容,看看它与键 1 的先前渲染相比是否发生了变化。它已经改变了,因此它完全重新渲染了该元素。然后它检查密钥 2。它的内容也发生了变化,因此会被重新渲染。整个列表都是如此。

现在假设每个项目都有一个在数据库中与其关联的唯一 ID,并且您将其指定为键。

<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
<Item key="834535">Apple</Item>

现在我们按字母顺序重新排序该列表:

<Item key="834535">Apple</Item>
<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>

此时,React 将检查密钥为 834535 的项目的内容是否仍然相同。嗯,内容are还是一样!因此,虽然该元素的顺序不同,但它是not重新渲染。然后检查key为782364的元素,发现其内容也相同。这也适用于整个列表。

在一个小列表中,您可能不会注意到动态生成的键与直接与该元素的数据绑定的键之间的区别,对于大型列表,性能优势是huge。这确实是 React 的主要吸引力——非常智能的重新渲染。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 React JS 不自动为动态子项生成键? 的相关文章

随机推荐

  • Laravel Eloquent 在 with() 函数中使用别名

    再会 laravel 中使用 with 函数时是否可以使用别名 举个例子 posts Post where condition gt with user as friend gt get 简短的回答是否定的 但您可以定义与要使用的别名的关系
  • 有聚合物模板的印章活动吗?

    我试图在每次标记其内容时将输入元素聚焦在聚合物模板内 问题是在模板加载之前我无法选择输入元素 目前 我只是使用 setTimeout 在模板加载后 100 毫秒集中输入 但我想知道是否有更优雅的解决方案 此外 自动对焦属性不起作用 因为模板
  • java regex,仅当不在引号或括号中时才以逗号分隔

    我想通过正则表达式进行java split 当字符串不在单引号或括号中时 我想在每个逗号上分割字符串 例子 Hello my friend how are you should give hello my friend how are yo
  • 搜索引擎可以读取 CSS 吗?

    我用标签来表示句子的重要性 然而 它破坏了页面风格的一致性 所以我用CSS把它改回来 结果是 对于访问者来说是相同的 但对于搜索引擎 SE 来说 显然是不同的 这正是SE们所烦恼的 所以我的问题是SE们能否读取CSS 并用它进一步判断整个页
  • 生成具有给定分布的随机数

    看看这个问题 快速选择随机数的概率 https stackoverflow com questions 26092977 swift probability of random number being selected 最上面的答案建议使
  • 如何防止 HTML 文本孤儿?

    我经常在图像周围包裹文字 有时文字包裹起来很笨拙 如下所示 在 HTML 中 图像向左浮动 文本如下 p img src images image p p This is my David Copperfield em I was born
  • 如果覆盖率低于一定百分比,则单元测试失败

    我制作了一个执行的 makefilego test cover 是否有可能失败make unit tests如果覆盖范围低于 X 则命令 我该怎么做呢 您可以使用TestMain在你的测试中做到这一点 TestMain 可以充当测试的自定义
  • 我可以将 JPA 2.0 与 Google App Engine 一起使用吗?

    我可以将 JPA 2 0 例如 EclipseLink 与 Google App Engine 一起使用吗 Google AppEngine 的 DataNucleus 插件支持 JDO 和 JPA API 来访问 Google AppEn
  • 将属性类型作为参数传递

    有没有办法将属性作为参数传递给函数 class Car let doors Int 4 let price Int 1000 有没有办法将 Car 属性作为类型传递给函数 我想实现以下目标 func f1 car Car property
  • 无法将 QMap 传递到 SLOT

    所以 这有效 h public slots void addMenu QString passedName signals void clicked const QString text cpp signalMapper new QSign
  • Spring JPA自定义查询与WHERE条件中的参数组合?

    如何在 Spring Data 中编写至少使用三个参数之一的 JPA 查询 我有这三个参数 Id PK Name Surname 客户端必须至少提供这三个参数之一 我想通过这些非空参数找到用户 是否可以为我的存储库创建此类自定义查询 或者我
  • SWIG 的 Python ctypes 回调函数

    我有一个 SWIG C 函数 它需要一个函数指针 WNDPROC 并且想给它一个由 ctypes WINFUNCTYPE 包装的 Python 函数 在我看来 这应该是兼容的 但 SWIG 的类型检查会引发异常 因为它不知道 ctypes
  • detached 和 allocateCurrentContext 是什么意思?

    当我将作业添加到队列中时 DispatchWorkItemFlags 为我们提供了几个选项可供选择 public func sync
  • 为所有图像添加前缀(递归)

    我有一个包含 5000 多张图像的文件夹 全部带有 JPG 扩展名 我想要做的就是递归地向所有图像添加 thumb 前缀 我发现了一个类似的问题 重命名文件和目录 添加前缀 https stackoverflow com questions
  • 地址栏中的 https 锁和公司名称

    我注意到在查看贝宝的网站时 他们的公司名称位于 Chrome 中的锁定图标旁边 这是因为他们创作了 ssl 证书 还是您认为他们是如何实现这一目标的 这是我一直很好奇的事情 但在搜索过程中我很难找到任何答案 您需要一个称为 扩展验证 EV
  • PowerPoint 命令,例如在 Office javascript API 上插入幻灯片或应用等效主题

    我正在开发一个 PowerPoint 加载项 将来它将在 Office Store 中发布 但它是VSTO项目 C 和winforms 无法发布 根据我的搜索 它一定是 Office Web Add in 项目 清单 xml 和网页 我正在
  • 如何让 NHibernate 缓存获取的子集合?

    我有一个相当简单的条件查询来获取子集合 如下所示 var order Session CreateCriteria
  • 自动化脚本:如果 FieldA = 1,则将 FieldB 设置为“one”

    我试图将这个问题分解为可管理的部分 空间查询 https stackoverflow com questions 56587515 maximo spatial query 我认为第一步是创建一个自动化脚本这样做是这样的 从字段中获取值 用
  • AWS Lambda 上的 Google-chrome

    是否可以在带有容器的 AWS Lambda 中使用 puppeteer 运行 Google chrome 而不是 Chromium 当我在浏览器中创建新页面时脚本卡住 const page await browser newPage 来自
  • 为什么 React JS 不自动为动态子项生成键?

    在编写 ReactJS 代码时 我必须为动态子项提供键 例如 render const options this state const availableOptions options map opt gt return