【问题标题】:Insert separators between multiple items, with key在多个项目之间插入分隔符,带键
【发布时间】:2019-01-21 16:26:43
【问题描述】:

我正在连续渲染几个数据项,用项目符号分隔,如果这些字符串不可用/不适用,有时会忽略它们。

const items = [
  age !== null && `age ${age}`,
  nationality && countryName(nationality),
  /* ... */
];
return <Text>{items.filter(x=>x).join(' • ')}</Text>;

我现在想把年龄数字加粗,所以我用片段替换了数组中的字符串:

[age !== null && (<Fragment>age <Text style={styles.ageNumber}>{age}</Text></Fragment>)]

重新组装它,我不能再做join,因为它只适用于字符串。相反,我用字符串文字穿插了它,

const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text>{intersperse(items.filter(x => x), ' • ')}</Text>;

现在我将一个数组传递给 React,而不是在 JavaScript 中组合它,我收到警告说我数组中的每个孩子都需要一个键。除了通过使用索引作为键引发更多警告之外,我如何很好地处理这个问题?

【问题讨论】:

标签: javascript arrays reactjs react-native


【解决方案1】:

您不需要创建节点数组,而是可以使用reduceFragment 的组合来创建最终节点而忘记键。

当您没有具有唯一键的数据时,此技术特别有用。

解决方案在这里?

【讨论】:

  • 嗨 Ganapati,这似乎可以避免警告,谢谢。像这样递归嵌套的 Fragment 树会不会让性能变差?
  • 我认为它不会对小列表产生任何性能问题,因为我们没有创建 DOM 节点,但它可能会在大列表上产生性能问题,因为在更改单个元素时会重新渲染所有内容.
【解决方案2】:

如果您的数组中没有唯一标识符,则只需创建您选择的唯一索引即可。就个人而言,我会这样做:

const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text key={`user-info-${Math.random()}`}>{intersperse(items.filter(x => x), ' • ')}</Text>;

当然,Math.random() 不一定会给您一个唯一的号码,但在大多数情况下通常就足够了。然而,如果你想 100% 确定你得到一个唯一的密钥,你可以改用 Lodash 的 uniqueId 方法:

import { uniqueId } from 'lodash/uniqueId';

const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text key={uniqueId('user-info-')}`}>{intersperse(items.filter(x => x), ' • ')}</Text>;

希望这会有所帮助。

编辑:

在 cmets 中讨论的更简单的解决方案:https://jsfiddle.net/jthcys8v/1/

没有理由将东西添加到数组中,因为您只是使事情复杂化。在我看来,这是一个更清洁的解决方案。您可以对此进行扩展并调用其他方法来实际渲染 AgeNationality 元素,例如

<div>
  {userInfo.age && this.renderAge()}
  {userInfo.nationality && this.renderNationality()}
</div>

【讨论】:

  • 嗨@tombraider,这似乎是在错误的级别上应用了密钥。需要键的是 Text 元素的内容,而不是 Text 元素本身。此外,使用随机数生成器不会导致不必要的重新渲染吗?
  • 关于不必要的重新渲染,您是绝对正确的。由于您指出的原因,这种方法绝不是最佳实践。这里有一些很好的信息:stackoverflow.com/questions/29808636/…。对于应用到错误级别的密钥,您可以简单地提升密钥生成并将其转移到正确的组件。
  • 为了解除密钥生成,您的意思是用intersperse(items.filter(x =&gt; x), ' • ').map(t=&gt;&lt;Fragment key={uniqueId('user-info-')}&gt;t&lt;/Fragment&gt;)} 替换散布,还是有更好的方法?
  • 您还有其他可以分享的代码吗,例如年龄和国籍的来源?这似乎不是最好的解决方案,而且在不知道您的数据如何传递的情况下提出建议有点困难。
  • 我正在获取有关用户的信息,因此 API 返回一个包含姓名、年龄、国籍和其他字段的用户对象。有时没有提供信息,所以它是空的。我想将此信息显示为副标题,如所述
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
相关资源
最近更新 更多