我有一个要使用React呈现为列表的对象列表。
反应需要list元素上的特殊key
属性,以便跟踪DOM和虚拟DOM之间的变化。
我的对象没有id
之类的特殊特殊属性,实际上,两个对象甚至可以具有相同的属性,但是对象本身是唯一的。
有没有一种方法可以使用对象的引用作为渲染React列表的键?
否则,在这种情况下可以建议什么解决方法?
另外,我正在从第三方接收项目列表,所以我不能随便给每个项目附加一个随机ID,因为这会使React在每次收到更新数据时重新渲染所有项目
答案 0 :(得分:0)
如果您没有唯一的ID(由后端返回,或者您无法在前端构建复合键),则可以将数组索引用作键:
render() {
return array.map((item, index) => <Item key={index} />)
}
在没有唯一ID的情况下,无论选择哪种方法,如果更改项目的顺序,则列表可能会完全混乱。
如果您的情况满足以下3个条件,则使用this article足够安全,使用此方法:
答案 1 :(得分:0)
将数组的
index
用作key
将是一场灾难,因为如果数组发生更改,则视图将无法正确更新,或者将以不可预测的方式部分更新。
我发现的唯一解决方案是按照注释中的建议生成虚拟ID。
想法是实现生成器,该生成器将为每个项目创建一个ID,但同时会记住以前生成的ID。
WeakMap JavaScript类将使我们能够存储项目对象引用和生成的ID之间的映射信息:
export class IdGenerator {
// Using WeakMap as index
map = new WeakMap();
// Internal counter
lastId = 0;
getItemId(item) {
// Getting previously generated ID for the specified item
let id = this.map.get(item);
// If item is new, generating the ID and storing it for future use
if (undefined === id) {
id = ++(this.lastId);
this.map.set(item, id);
}
// Returning ID to the caller in either case
return id;
}
}
然后可以在呈现列表之前将其用于为每个项目分配生成的ID:
class ListBox extends Component {
// Instantiating the generator
itemsIdGenerator = new IdGenerator();
render() {
return (
<ul>
{this.props.items.map(item => (
<li key={this.itemsIdGenerator.getItemId(item)}>
{item.title}
</li>
))}
</ul>
);
}
}
但是请确保为组件的每个实例使用不同的生成器实例,并且仅使用该组件创建一次生成器。
此外,调用组件的render方法中每个项目的生成器可能不是最佳的。但是,我不想触摸原始项目或更改它们。如果这是一个问题,请考虑在props更改时使用React提供的各种生命周期方法来设置ID。