React报错:子元素key重复,使用useContext后出现该问题
问题解决笔记:React笔记应用重复key问题
核心问题分析
- ID生成逻辑错误:你在App组件外部只调用了一次
uuid()生成small_id,所有初始笔记和新增笔记都复用这个ID,直接导致React列表渲染时的key完全重复,这是根本原因,和useContext无关。 - useContext未正确使用:你改用Context传递
addHandleNote后,AddNote组件仍然在尝试通过props接收这个函数,根本没从Context里拿值,等于白改了Context。
分步修复
1. 修复ID生成逻辑
修改App.js,确保每个笔记都有唯一ID:
- 初始笔记的每个对象单独生成ID
- 新增笔记时,每次都生成新的ID
修改后的App.js关键部分:
import { useState } from "react"; import { v4 as uuid } from "uuid"; import NotesList from "./components/NotesList"; import HandleAddContext from "./components/UseContext/HandleAddContext"; // 生成单个短ID的工具函数 const generateSmallId = () => uuid().slice(0, 8); // 初始状态每个笔记用独立ID const initialState = [ { id: generateSmallId(), text: "1st note", date: "12/10/2022", }, { id: generateSmallId(), text: "2nd note", date: "15/10/2022", }, { id: generateSmallId(), text: "3rd note", date: "16/10/2022", }, { id: generateSmallId(), text: "4th note", date: "30/10/2022", }, ]; export const App = () => { const [notes, setNotes] = useState(initialState); // 变量名修正:setNote → setNotes,更语义化 const addHandleNote = (text) => { const date = new Date(); const newNote = { id: generateSmallId(), // 每次新增都生成新ID text: text, date: date.toLocaleDateString(), }; const newNotes = [...notes, newNote]; setNotes(newNotes); }; return ( <HandleAddContext.Provider value={addHandleNote}> <div className="container"> <NotesList notes={notes} /> </div> </HandleAddContext.Provider> ); }; export default App;
2. 修复AddNote的Context消费逻辑
修改AddNote.js,用useContext获取addHandleNote,不再依赖props:
import { useState, useContext } from "react"; // 导入useContext import { RiSave2Line } from "react-icons/ri"; import HandleAddContext from "./UseContext/HandleAddContext"; // 导入Context const AddNote = () => { // 移除props参数 const [addText, setAddText] = useState(""); const [errorMsg, setErrorMsg] = useState(""); const handleAddNote = useContext(HandleAddContext); // 从Context获取函数 const handleChange = (e) => { setAddText(e.target.value); }; const handleSaveClick = () => { if (addText.trim().length > 0) { handleAddNote(addText); } }; return ( <div> <textarea rows="8" cols="10" placeholder="Type here to add a note..." value={addText} onChange={handleChange} /> <div> <p>200 characters remaining</p> <RiSave2Line onClick={handleSaveClick} /> </div> </div> ); }; export default AddNote;
3. 其他小修正
- NotesList里不需要给AddNote传props了,保持现有代码即可
- 初始状态里的日期写错了,
22022改成2022(可选,不影响功能但更合理)
验证效果
修改后,每个笔记都会有唯一的ID,React列表渲染的key不再重复,同时AddNote也能正确通过Context调用添加笔记的函数,问题解决。
内容的提问来源于stack exchange,提问作者N S
相关产品推荐
相关产品推荐

