Preact渲染的组件错误

Preact渲染的组件错误,第1张

Preact渲染的组件错误

这是一个经典的问题,Preact的文档完全没有解决这个问题,因此我想为此道歉!如果有人感兴趣,我们一直在寻求帮助以编写更好的文档。

这里发生的事情是您将Array的索引用作键(在render中的地图中)。这实际上只是一个模拟的虚拟域差异是如何工作的默认值-
键始终

0-n
哪里
n
是数组的长度,因此删除任何项目简单地脱落列表中的最后关键。

说明:按键超越渲染

在您的示例中,想象一下(虚拟)DOM在初始渲染中的外观,然后在删除项目“ b”(索引3)之后的外观。在下面,让我们假设您的列表只有3个项目(

['a','b', 'c']
):

以下是初始渲染产生的结果:

<div>  <div className="title">Packages</div>  <div className="packages">    <div className="package" key={0}>      <button>X</button>      <Package tracking="a" />    </div>    <div className="package" key={1}>      <button>X</button>      <Package tracking="b" />    </div>    <div className="package" key={2}>      <button>X</button>      <Package tracking="c" />    </div>  </div></div>

现在,当我们在列表中的第二项上单击“ X”时,“ b”将传递到

removePackage()
,设置
state.packages
['a','c']
。这将触发我们的渲染,生成以下(虚拟)DOM:

<div>  <div className="title">Packages</div>  <div className="packages">    <div className="package" key={0}>      <button>X</button>      <Package tracking="a" />    </div>    <div className="package" key={1}>      <button>X</button>      <Package tracking="c" />    </div>  </div></div>

由于VDOM库只知道您在每个渲染器上赋予它的新结构(而不​​是如何从旧结构更改为新结构),因此键所做的基本上是告知项目

0
1
保留在原位-
我们知道是错误的,因为我们希望
1
删除索引处的项目。

切记:

key
优先于默认的子diff重新排序语义。在此示例中,由于
key
始终只是基于0的数组索引,因此最后一项(
key=2
)会被丢弃,因为它是后续渲染中缺少的一项。

修复

因此,要修正您的示例-您应该使用可以识别 项目 而不是其 偏移量
的键作为键。这可以是项目本身(任何值都可以作为键),也可以是

.id
属性(首选,因为它避免了在对象周围散布对象引用,从而避免了GC):

let packages = this.state.packages.map((tracking, i) => {  return ( // ↙️ a better key fixes it :)    <div className="package" key={tracking}>      <button onClick={this.removePackage.bind(this, tracking)}>X</button>      <Package tracking={tracking} />    </div>  );});

ew,这比我原本打算的要长得多。

TL,DR:
切勿将数组索引(迭代索引)用作

key
。充其量,它模仿的是默认行为(自上而下的子级重新排序),但更多情况下,它只是将所有差异推送到最后一个子级。


编辑:
@tommy建议将此链接链接到eslint-
plugin-react docs,这比我上面做的要好。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5646510.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存