reactjs – React中重复元素的密钥管理

我需要一个组件,给一些孩子,它会一遍又一遍地重复这些孩子来填充屏幕.让我们说它有一个像这样的简单降价:

<FillScreen items={[
    { id: 'one', content: 'foo' },
    { id: 'two', content: 'bar' }
]} />

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

<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.

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

   <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>

编辑 – 请注意,这些元素正在生成一个数组,这就是我们需要指定一个键的原因

我看到这种方法存在两个问题:

>在这一点上,我可能只是摆脱原始密钥,只使用一个索引,这是绝对不鼓励的.
>我的真实组件,你给这个组件的项目的方式是通过孩子(我在这里过分简化以获得重点),所以我必须克隆每个元素只是为了更改密钥.

解决方案B.

使用片段分隔循环

   <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>

在这里感觉更干净,但与此同时,这不是碎片首先被添加的原因,所以也许是在滥用它们?

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

最佳答案 由于您使用的是Fragment,我假设您使用的是版本> 16.在这种情况下,我认为还有另一种(可能更好的)方法来解决这个问题,即返回一个数组数组.像这样的东西:

[
  [
    <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”“相当”,但恕我直言不那么“hacky”,因为我认为Fragment并不是那样用的.让我继续说:

在版本16之前,渲染函数无法返回反射元素数组,这非常令人讨厌.在版本16开始可能的情况下,但是Array的元素必须始终具有一个键,以便React的协调器正常工作,这意味着从渲染函数返回它是错误的:

[
  <span>foo</span>,
  <span>bar</span>,
] 

这是正确的:

[
  <span key="firstSpan">foo</span>,
  <span key="secondSpan">bar</span>,
] 

但这样做有点奇怪和烦人.这就是Fragment被发明的原因,所以我们可以回复:

<Fragment>
  <span>foo</span>
  <span>bar</span>
</Fragment>

因此,Fragment的最大优点是我们不必为其子元素分配键.这就是为什么我觉得看到一个带有“键控”孩子的碎片有点蠢蠢欲动.

另外,我想说我认为你的“选项A”没有任何问题.但是,我认为在大多数情况下,我提出的解决方案将更容易实现.

点赞