React使子级不参与上一次渲染



我在基于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,所以我无法复制它(。

所以,任何面临类似问题的人:去检查你的密钥在页面中是否真正唯一,因为加载新模板后会发生什么:

  1. React想要删除旧项目
  2. 它为每个键搜索相应的DOM元素,找到具有key="XXX"的项并将其从DOM中删除
  3. 当处理相应的键时,它们的重复项会留在DOM中,React不再关心这个特定的键
  4. 我们加载新模板,并将它们附加到父容器中
  5. 哇!我们在新加载之前有旧项目

我在这里做了什么-我现在的关键是:

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)

相关内容

  • 没有找到相关文章

最新更新