React列表报unique 'key' prop错误,已设唯一person.id仍无效如何解决?
问题根本原因
- 第一个警告的成因:你所验证的
person.id全局唯一不代表它在每次渲染的单组rowList中都是有效值,大概率存在个别项的person.id为undefined、null、空字符串,或是同个rowList内出现重复id,导致同个map循环下出现重复key,拼接索引后相当于给key加了兜底校验,因此第一个警告消失。 - 第二个警告的成因:90%以上概率是你的
ImageComponent内部存在数组map渲染JSX的逻辑,且返回的最外层元素没有设置唯一key,你之前只排查了RowComponent层级的key,没有检查子组件内部的列表渲染逻辑。
完整解决办法
- 验证
rowList内所有项的id有效性:在RowComponent的map循环中打印每一项person.id,确认无无效值、同组内无重复,如果确认所有id都有效,完全可以去掉拼接的索引,直接用person.id作为key即可。 - 检查
ImageComponent的代码:找到所有数组调用map返回JSX的逻辑,给返回的最外层JSX元素添加当前map循环内的唯一key即可解决第二个警告。 - 额外优化(可选):当前
GamePage每次重渲染都会重新生成随机列表,建议用useMemo缓存计算结果,减少不必要的重渲染和diff阶段的异常:
import React, { useMemo } from 'react' import { Grid, Image } from 'semantic-ui-react' const RowComponent = ({ rowList, personToFind }) => <Grid.Row columns={3} centered> {rowList.map(person => <Grid.Column key={person.id}> <ImageComponent person={person} personToFind={personToFind} /> </Grid.Column>) } </Grid.Row> const GamePage = React.memo(({ peopleList }) => { // 缓存随机列表计算逻辑,仅当peopleList变化时重新生成 const randomPeopleList = useMemo(() => getNRandomItems(peopleList, 6), [peopleList]) const topRow = useMemo(() => randomPeopleList.slice(0, 3), [randomPeopleList]) const bottomRow = useMemo(() => randomPeopleList.slice(3), [randomPeopleList]) const personToFind = useMemo(() => getRandomItem(randomPeopleList), [randomPeopleList]) return ( <Grid> <RowComponent rowList={topRow} personToFind={personToFind} /> <RowComponent rowList={bottomRow} personToFind={personToFind} /> </Grid> ) })
如果完成上述操作后警告仍存在,可以查看控制台报错的完整信息,报错信息会明确标注触发警告的组件名称,直接定位到对应组件的列表渲染逻辑即可。
内容的提问来源于stack exchange,提问作者Nikita Vlasenko
相关产品推荐
相关产品推荐

