React使用useState添加列表项时报unique key唯一属性警告如何解决?
警告触发原因
React在渲染数组生成的列表节点时,要求每个同级列表项必须配置唯一的非undefined的key属性,该属性用于React做虚拟DOM的Diff对比,精准识别节点的增删改顺序,避免不必要的节点重渲染。
你当前的代码触发警告有两个直接原因:
- 你往
state数组中存入的是原始JSX元素,而非结构化数据,这些JSX元素本身没有id属性,你在map遍历取item.id作为key时,拿到的实际是undefined,所有列表项的key值完全重复,不符合React的要求。 - 直接将JSX存入state属于不规范的写法,state应该仅存储可序列化的业务数据,渲染逻辑统一放在组件渲染阶段处理,否则后续会引发更多状态更新、节点复用相关的问题。
功能能正常渲染只是因为React在key不唯一时做了向下兼容,但会丢失列表更新的性能优化,且有概率出现节点内容渲染错乱的问题。
附警告截图:
修复方案
修改state的存储结构,仅存入列表的结构化数据,每条数据自带唯一id,渲染阶段再根据数据生成对应的JSX节点,示例修复代码如下:
const NewItem: React.FC = () => { // state仅存储结构化数据,不直接存储JSX const [state, setState] = useState<{id: number, content: string}[]>([]); function addItem() { setState([ ...state, // 每条数据自带唯一id,可根据业务场景选用时间戳、自增数字、uuid等方案 { id: Date.now(), content: 'This is a Test' } ]); } return ( <> <AllBets> {state.map((item) => ( // 直接取每条数据的唯一id作为key,保证全局不重复 <BetsRange key={item.id} id={'div-parent'}> <div>{item.content}</div> </BetsRange> ))} </AllBets> <AddItem onClick={addItem}></AddItem> </> ) }
如果你的列表项确实没有可以作为唯一标识的业务字段,也可以临时使用map方法的第二个参数(数组下标)作为key,但该方案仅适用于不会发生列表项增删、排序的静态列表,否则依然会有节点渲染错乱的隐患:
// 仅静态列表可用的临时兼容方案 {state.map((item, index) => ( <BetsRange key={index} id={'div-parent'}> {item} </BetsRange> ))}
内容的提问来源于stack exchange,提问作者Guilherme
相关产品推荐
相关产品推荐

