首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反作用中重复元素的关键管理

反作用中重复元素的关键管理
EN

Stack Overflow用户
提问于 2019-01-15 09:55:59
回答 2查看 741关注 0票数 4

我需要一个组件,给一些孩子,它会重复这个孩子一遍又一遍地填充屏幕。假设它有这样一个简单的标记:

代码语言:javascript
复制
<FillScreen items={[
    { id: 'one', content: 'foo' },
    { id: 'two', content: 'bar' }
]} />

在内部,此组件将获得屏幕大小,并最终将这些项填充到屏幕上。生成的DOM如下所示:

代码语言:javascript
复制
<div class="fill-screen">
   <div>foo</div>
   <div>bar</div>
   <div>foo</div>
   <div>bar</div>
   <div>foo</div>
   <div>bar</div>
   <div>foo</div>
</div>

我遇到的问题是,当这个元素计算出它需要呈现7个元素时,我不能直接使用items[i].id作为每个元素的键,因为会有重复的键。

我不知道解决这个问题的最佳模式是什么,我想出了两种可能的解决方案,但我并不完全喜欢:

解A

在每个键上追加一个循环索引,因此呈现中的数组包含以下JSX:

代码语言:javascript
复制
   <div key='one-0'>foo</div>
   <div key='two-0'>bar</div>
   <div key='one-1'>foo</div>
   <div key='two-1'>bar</div>
   <div key='one-2'>foo</div>
   <div key='two-2'>bar</div>
   <div key='one-3'>foo</div>

编辑-注意这些元素正在生成到一个数组中,这就是为什么我们需要指定一个key

我认为这种做法有两个问题:

  • 在这一点上,我可能只是摆脱原来的键,只使用一个索引,这是绝对不鼓励的。
  • 我的真实组件,您给这个组件的方式是通过子类(我在这里简化得太简单了,这样就可以理解),所以我必须克隆每个元素来更改键。

解B

使用片段在循环之间分离

代码语言:javascript
复制
   <Fragment key={0}>
     <div key='one'>foo</div>
     <div key='two'>bar</div>
   </Fragment>
   <Fragment key={1}>
     <div key='one'>foo</div>
     <div key='two'>bar</div>
   </Fragment>
   <Fragment key={2}>
     <div key='one'>foo</div>
     <div key='two'>bar</div>
   </Fragment>
   <Fragment key={3}>
     <div key='one'>foo</div>
   </Fragment>

在这里它感觉更干净,但同时这并不是最初添加碎片的原因,所以它可能是在滥用它们吗?

这个问题有更好的解决办法吗?社区标准是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-15 10:47:49

由于您使用的是Fragment,我假设您使用的是版本>16。在这种情况下,我认为还有另一种(也许更好)解决这个问题的方法,就是返回数组。就像这样:

代码语言:javascript
复制
[
  [
    <div key='one'>foo</div>,
    <div key='two'>bar</div>,
  ],
  [
    <div key='one'>foo</div>,
    <div key='two'>bar</div>,
  ],
  [
    <div key='one'>foo</div>,
  ],
]

实际上,这与您的“解决方案B”是“等效的”,但是IMHO没有那么“烦琐”,因为我认为Fragment不应该像那样使用。请允许我对此作进一步阐述:

在版本16之前,呈现函数无法返回一个由React元素组成的数组,这是非常烦人的事情。但是,在开始可能出现的版本16上,数组的元素必须始终有一个key,这样function的协调器才能正常工作,这意味着从呈现函数返回它是不好的:

代码语言:javascript
复制
[
  <span>foo</span>,
  <span>bar</span>,
] 

这是正确的:

代码语言:javascript
复制
[
  <span key="firstSpan">foo</span>,
  <span key="secondSpan">bar</span>,
] 

但这样做有点奇怪也很烦人。这就是为什么发明了Fragment,这样我们就可以返回以下内容:

代码语言:javascript
复制
<Fragment>
  <span>foo</span>
  <span>bar</span>
</Fragment>

因此,Fragment的最大优点是我们不必将keys分配给他们的子元素。这就是为什么我觉得看到一个“键控”孩子的Fragment有点烦人的原因。

另外,我想说,我不认为你的“选择A”有什么问题。但是,我认为在大多数情况下,我提出的解决方案将更容易实现。

票数 1
EN

Stack Overflow用户

发布于 2019-01-15 11:15:34

作为密钥使用的正确方法取决于在父组件(FillScreen)的生命周期中可以更改什么。

使用索引作为键通常是不允许的,因为如果items支持在FillScreen的生命周期中发生了变化,那么相同的索引现在可以指向另一个项,但是组件不会重新呈现,因为键保持不变。

在这种情况下,您可以简单地使用idindex的组合作为关键,但请记住,如果在数组中重新设置了项,那么用于显示每个项的组件将被重新挂载。对片段使用索引键的另一种方法也是如此(在这里使用片段没有什么特别的优势)。

类似地,如果在数组之间注入项,则用于显示所有后续项的组件将被丢弃并重新创建。

如果您确实希望对上述情况进行优化,则可以通过附加该id的出现索引来构造密钥。

代码语言:javascript
复制
<div class="fill-screen">
   <div key="one-0">foo</div>
   <div key="two-0">bar</div>
   <div key="one-1">foo</div>
   <div key="two-1">bar</div>
   <div key="one-2">foo</div>
   <div key="two-2">bar</div>
   <div key="one-3">foo</div>
</div>

React元素相当轻量级,因此克隆不会带来很大的开销。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54196477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档