我在基于redux中存储的模板数组呈现页面时遇到问题。我无法提供实际的代码,因为它太复杂了,无法在沙箱中复制,但我会尝试简化结构。
我有基于flex-grow
的pinterest样式网格,并根据每个项目的尺寸对其进行js计算,所以我需要将所有这些都放在一个容器中。
我在同一个div中有3组项目:
blank_item
+templates.map
+tailItems.map
<div className="grid">
{shouldRenderBlankItem && <BlankItem />}
{templates.map((template) => (
<Template
key={template.uuid}
template={template}
/>
))}
{shouldRenderTail &&
tailItems.map(item, i) => (
<TailItem
key={i}
item={item}
/>
))}
</div>
问题是,有时在渲染后,我会从上一次渲染中留下EXTRA子元素,React会将它们放在div.grid
中的其他元素前面,所以我得到的结果看起来像:
3-4 of EXTRA <Template/>
+blank_item
+templates.map
+tailItems.map
作为模板的密钥,我使用来自后端的template.uuid
,我知道它们是唯一的,react也不会显示任何重复密钥的警告-所以我知道我没有从API获得任何重复项,我认为这可能是一个问题。
Redux很好——我在其中看到了正确数量的templates
,例如50,grid
和react dev工具在我检查父组件时显示了相同的50个模板作为道具,但实际的DOM在同一时刻有例如53个元素。
如何调试这样的问题?我想在对账过程中出现了问题,但我不知道从哪里开始调试。
我有React/RectDOM 16.13.1
好的,所以在我的案例中问题是后端api坏了,它可能会两次返回相同的模板-所以我用于键的uuid对于每个模板都是唯一的,但就页面和DOM元素而言,它们并不是真正唯一的。
我只在生产构建中遇到过这种情况,这就是为什么我没有duplicated key
警告的原因(在开发构建中,我有另一个模板少得多的DB,所以我无法复制它(。
所以,任何面临类似问题的人:去检查你的密钥在页面中是否真正唯一,因为加载新模板后会发生什么:
- React想要删除旧项目
- 它为每个键搜索相应的DOM元素,找到具有
key="XXX"
的项并将其从DOM中删除 - 当处理相应的键时,它们的重复项会留在DOM中,React不再关心这个特定的键
- 我们加载新模板,并将它们附加到父容器中
- 哇!我们在新加载之前有旧项目
我在这里做了什么-我现在的关键是:
templates.map((template, i) => <Template key={template.uuid + i} />
所以在这种情况下,即使后端返回重复的项目,我也是安全的。当然,我们也会修复后端。感谢您的阅读和帮助!
快速示例如何在data
:中搜索具有相同id
的项目
var duplicates = new Set();
data.map(t => t.id).forEach((id, i, arr) => {if(arr.filter(item => item == id).length > 1){
duplicates.add(id);
}});
console.log("DUPLICATED IDs:", duplicates)