我有一个项目列表,其中包含的数据不足以生成唯一密钥。如果我使用uuid库生成ID,那么单个项目的更改还会导致其他项目重新呈现,因为它们的密钥每次都会更改吗?
const people = [
{
gender: 'male',
firstName: 'david',
},
{
gender: 'male',
firstName: 'david',
},
{
gender: 'male',
firstName: 'joe',
},
]
const renderPeople = () => {
return people.map(person => {
return (
<div key={uuid.v4() /* a new value each time? */ }>
<p>{person.gender}</p>
<p>{person.firstName}</p>
</div>
)
})
}
过了一会儿...一位大卫变了
const people = [
{
gender: 'male',
firstName: 'david',
},
{
gender: 'male',
firstName: 'davidzz',
},
{
gender: 'male',
firstName: 'joe',
},
]
答案 0 :(得分:0)
是的。按键应该稳定。如果不是这样,React无法推断出这些项目可能完全相同,而必须完全重新渲染它们。
答案 1 :(得分:0)
<div key={uuid.v4()}>
每次都为每个<div>
分配一个新密钥,因此它毫无用处。
如果数组保持不变,则应在创建数组时生成UUID。
如果数组更改,例如从HTTP请求收到后,将再次生成具有相同内容的元素的UUID。
为了避免这种情况,key
应该特定于person
实体。始终最好使用内部标识符(数据库ID),以免产生歧义。
如果标识符不可用,key
可能取决于元素内容:
return (
<div key={JSON.stringify(person)}>
<p>{person.gender}</p>
<p>{person.firstName}</p>
</div>
)
在创建数组时对元素进行一次哈希比较有效,例如与uuid
:
import uuidv3 from 'uuid/v3';
...
for (const person of people) {
person.key = uuidv3(JSON.stringify(person), uuidv3.URL);
}
或使用专用的哈希函数,例如object-hash
。
请注意,如果元素内容相同,则散列可能会导致键冲突。
答案 2 :(得分:0)
如前所述,密钥必须稳定。为了实现这一点,我有一个建议给你。
我发现使用 UUID 作为键非常简单和方便。我将它们用作单例并使用钩子创建它们。
export function useSingleton<T>(provider: () => T): T {
const singleton = useRef<T>();
function getSingleton() {
if (singleton.current == null) {
singleton.current = provider();
}
return singleton.current;
}
return getSingleton();
}
export function useComponentId(): string {
return useSingleton(uuidv4);
}
然后像这样使用
const componentId = useComponentId();
...
something.map((thing, index) =>
<Component key={`${componentId}.label.${index}`}/>
);
这只是一个使用示例。我不会说在那种情况下你需要一个 UUID。例如当您的“事物”对象没有唯一 ID 时,它非常方便。它比计算散列或执行 JSON.stringify() 快得多。也没有碰撞的危险。