React列表unique key prop不生效,如何解决该警告?
解决React列表"key"属性警告问题
问题概述
提交表单后尝试在新页面展示数据,已通过uuid生成唯一ID并给列表子项的div设置了key属性,但仍收到警告:
Warning: Each child in a list should have a unique "key" prop
问题原因
警告并非来自AnimalDetails组件的map循环(此处的key设置是正确的),而是来自表单部分的<ul>元素:
<ul>的直接子元素包含<input>和条件渲染的<span>错误提示,React会将这些零散元素视为无唯一标识的列表- 虽然给
<input>设置了固定key,但条件渲染的<span>没有key,且<ul>的子元素结构不符合语义规范(<ul>的合法直接子元素应为<li>),导致React无法正确识别每个元素的唯一性
解决方案
- 将每个表单字段(输入框+错误提示)包裹在
<li>标签内,符合<ul>的语义要求 - 给每个
<li>设置唯一的key,确保<ul>的直接子元素都有唯一标识 - 移除原
<input>上的key,因为它们不再是<ul>的直接子元素
修改后的表单组件代码
import { useState } from "react"; import { useForm } from "react-hook-form"; import { useLocalStorage } from "react-use"; import useLocalStorageState from "use-local-storage-state"; import { v4 as uuidv4 } from "uuid"; import AnimalDetails from "./AnimalDetails"; export default function AddAnimalForm() { // 建议统一使用一种本地存储钩子,避免数据同步问题 const [animalData, setAnimalData] = useLocalStorage("Animal Data", []); const [animals, setAnimals] = useLocalStorageState("animals", []); const [submitMessage, setSubmitMessage] = useState(false); const [showDetails, setShowDetails] = useState(false); const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = (data, event) => { event.target.reset(); const id = uuidv4(); const newAnimalData = { ...data, id: id }; setAnimalData([...animalData, newAnimalData]); setAnimals([...animals, newAnimalData]); setSubmitMessage(true); setShowDetails(true); setTimeout(() => { setSubmitMessage(false); setShowDetails(false); }, 3000); }; return ( <div> <form onSubmit={handleSubmit(onSubmit)}> <select {...register("species", { required: true })}> <option value="">--Choose Animal--</option> <option value="dog">Dog</option> <option value="cat">Cat</option> <option value="rabbit">Rabbit</option> <option value="tortoise">Tortoise</option> <option value="guinea pig">Guinea pig</option> </select> {errors.species && <span>Species is required</span>} <ul> <li key="name-field"> <input {...register("name", { required: true })} placeholder="Name" /> {errors.name && <span>Name is required</span>} </li> <li key="age-field"> <input {...register("age", { required: true })} placeholder="Age" /> {errors.age && <span>Age is required</span>} </li> <li key="character-field"> <input {...register("character", { required: true })} placeholder="Character" /> {errors.character && <span>Character is required</span>} </li> <li key="owner-field"> <input {...register("owner", { required: true })} placeholder="Owners" /> {errors.owner && <span>Owners is required</span>} </li> <li key="miscellaneous-field"> <input {...register("miscellaneous")} placeholder="miscelleaneous" /> </li> </ul> <input type="submit" /> </form> {submitMessage && <p>Form submitted successfully</p>} {showDetails && <AnimalDetails animals={animals} />} </div> ); }
额外建议
代码中同时使用了useLocalStorage和useLocalStorageState两个不同的本地存储钩子,存储键分别为"Animal Data"和"animals",可能导致数据同步不一致。建议统一使用其中一个钩子,比如:
// 统一使用useLocalStorageState const [animals, setAnimals] = useLocalStorageState("animals", []); // 移除animalData相关的代码,直接使用animals即可
内容的提问来源于stack exchange,提问作者Pekz
相关产品推荐
相关产品推荐

