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

React列表key警告排查:已设唯一key仍报错(useContext+useReducer)

问题:React列表已设唯一key仍报key警告

已在home.js中为列表项设置blog._id作为唯一key,但仍收到以下警告:

react-jsx-dev-runtime.development.js:87 Warning: Each child in a list should have a unique "key" prop.
Check the render method of Home.
at Blogdetails (http://localhost:3000/static/js/bundle.js:129:5)

项目使用useContext + useReducer管理状态,核心相关代码如下:

home.js

import{useEffect} from 'react'
import Blogdetails from '../components/blogdetails'
import Form from '../components/form'
import { useBlogContext } from '../hooks/useblog'

 const  Home=()=> {

 const {blogs, dispatch} =useBlogContext()

  useEffect(()=>{
    const  fetchBlogs= async()=>{
      const blogPost= await fetch('/api/workouts')
      const res=await  blogPost.json()
      if(blogPost.ok){
        dispatch({type:'CREATE_BLOG', payload:res})
      }
    }
    fetchBlogs()
// eslint-disable-next-line 
  },[])

return (
    <div className="home">
    <div className="worksouts">
      {blogs && blogs.map((blog)=>(
          <Blogdetails key={blog._id} blog={blog}/>
      ))}
    </div>
      <Form/>
    </div>
  )
}

export default Home

blogcontext.js

import { createContext, useReducer } from 'react';

export const blogContext = createContext();

export const BlogReducer = (state, action) => {
  switch (action.type) {
    case 'GET_ALL_BLOGS':
      return {
        blogs: action.payload,
      };
    case 'CREATE_BLOG':
      return {
        blogs: [action.payload, ...state.blogs],
      };
    default:
      return state;
  }
};

export const BlogContextprovider = ({ children }) => {
  const [state, dispatch] = useReducer(BlogReducer, {
    blogs: [],
  });
  return (
    <blogContext.Provider value={{ ...state, dispatch }}>
      {children}
    </blogContext.Provider>
  );
};

其余代码(blogdetails.js、form.js、useblog.js、index.js)见原提问。


核心问题定位

初始加载博客列表时,错误使用了CREATE_BLOG action类型:后端返回的res是所有博客的数组,但CREATE_BLOG的处理逻辑是将payload放到数组开头,导致state中的blogs变成[数组, ...原空数组]的嵌套结构。此时map循环时,第一个元素是整个博客数组而非单个博客对象,blog._id不存在(或为undefined),触发key重复警告。

修复步骤

1. 修正初始加载的action类型

在home.js的useEffect中,将dispatch的action类型改为GET_ALL_BLOGS:

// home.js 中 useEffect 内的修改
if(blogPost.ok){
  dispatch({type:'GET_ALL_BLOGS', payload:res}) // 替换 CREATE_BLOG 为 GET_ALL_BLOGS
}

GET_ALL_BLOGS会直接将后端返回的博客数组赋值给state.blogs,保证结构为单个博客对象的数组。

2. 验证数组结构

在home.js的return语句前添加日志,确认blogs结构正确:

console.log('当前blogs结构:', blogs)

正常输出应为类似:[{_id: '123', title: '测试标题', des: '测试描述'}, ...]。

3. 可选:增加边界处理

为避免后端返回异常数据(如无_id的项),可在map时过滤无效项:

{blogs && blogs.map((blog)=>{
  if(!blog?._id) return null;
  return <Blogdetails key={blog._id} blog={blog}/>
})}

补充说明

添加新博客时使用CREATE_BLOG是正确的,因为此时payload是单个博客对象,[action.payload, ...state.blogs]会将新博客添加到数组开头,保持结构正常。


内容的提问来源于stack exchange,提问作者me boros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:33:14