You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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无法正确识别每个元素的唯一性

解决方案

  1. 将每个表单字段(输入框+错误提示)包裹在<li>标签内,符合<ul>的语义要求
  2. 给每个<li>设置唯一的key,确保<ul>的直接子元素都有唯一标识
  3. 移除原<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:35:18