问题
I have a list of items that doesn't contain enough data to generate a unique key. If I use the uuid library to generate an ID, will a single item change also causes the other items to re-render since their key will change each time?
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>
)
})
}
some time later... one of the davids changed
const people = [
{
gender: 'male',
firstName: 'david',
},
{
gender: 'male',
firstName: 'davidzz',
},
{
gender: 'male',
firstName: 'joe',
},
]
回答1:
<div key={uuid.v4()}>
assigns new key for each <div>
every time, so it is useless.
If the array stays same, UUID should be generated on array creation.
If the array changes, e.g. received from HTTP request, UUIDs for elements with same content will be generated again.
In order to avoid that, key
should be specific to person
entity. It's always preferable to use internal identifiers (database IDs) where available for unambiguity.
If identifiers are not available, key
may depend on element contents:
return (
<div key={JSON.stringify(person)}>
<p>{person.gender}</p>
<p>{person.firstName}</p>
</div>
)
It's more efficient to hash elements once at the time when an array is created, e.g. with uuid
:
import uuidv3 from 'uuid/v3';
...
for (const person of people) {
person.key = uuidv3(JSON.stringify(person), uuidv3.URL);
}
Or use dedicated hashing function like object-hash.
Notice that hashing may result in key collisions if there are elements with same contents.
回答2:
Yes. Keys should be stable. If they're not, React can't infer that these items might be the same at all, and has to fully rerender them.
来源:https://stackoverflow.com/questions/52705335/will-using-uuid-to-as-list-keys-cause-unnecessary-re-renders-in-react