React待办列表移除按钮失效及控制台警告问题求助
React Todo List移除按钮失效及控制台警告修复
问题现象
- 为Todo List添加移除功能后,移除按钮无法正常工作;移除该功能后,其他模块运行正常
- 控制台抛出两个警告:
react-dom.development.js:86 Warning: Cannot update a component (Todo) while rendering a different component (ToDoList).react-jsx-dev-runtime.development.js:87 Warning: Each child in a list should have a unique "key" prop.
相关代码
ToDo.js
import React, { useState } from 'react' import AddNew from './Addnew'; import ToDoList from './ToDoList'; function Todo() { const[toDoList, setToDoList] = useState([]); function addNew(addText, date){ const obj = { text : addText, expiry : date, completed : false } const newToDo = [...toDoList, obj]; setToDoList(newToDo); } function handleCheck(index){ const newToDOs = [...toDoList]; newToDOs[index].completed = !newToDOs[index].completed; setToDoList(newToDOs); } function RemoveList(index){ const newTo = [...toDoList]; newTo.splice(index,1); setToDoList(newTo); } return ( <> <h1>To Do List</h1> <AddNew addNew={addNew}/> <ul className="list-group"> <ToDoList list={toDoList} handleCheck={handleCheck} RemoveList={RemoveList} /> </ul> </> ); } export default Todo;
ToDoList.js
import React from "react"; function ToDoList(props) { return ( <> {props.list.map((element, index) => { return ( <> <li className={ element.completed ? "list-group-item yes-comp" : "list-group-item no-comp" } > <span className="badge text-bg-info">{index + 1}</span>   <input type="checkbox" defaultChecked={element.completed} onChange={() => { props.handleCheck(index); }} />{" "}   {element.text} <span className="badge text-bg-light"> {element.expiry.toString().slice(4, 15)} </span> <button className="btn btn-danger" onChange={props.RemoveList(index)} >Remove</button> </li> </> ); })} </> ); } export default ToDoList;
AddNew.js
import React, { useState } from "react"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; function AddNew(props) { const [startDate, setStartDate] = useState(new Date()); const [input, setInput] = useState(""); function submitData() { props.addNew(input, startDate); setInput(""); } return ( <> <div className="Container InputContain"> <input className="form-control" placeholder="Add New in To Do List" value={input} onInput={(e) => setInput(e.target.value)} /> <div> <DatePicker className="AddDate" selected={startDate} onChange={(date) => setStartDate(date)} /> <button className="btn btn-primary btn-cust" onClick={submitData}>Add</button> </div> </div> </> ); } export default AddNew;
修复方案
1. 修复移除按钮失效及组件更新警告
问题出在ToDoList.js的移除按钮上:
- 错误使用
onChange事件(按钮应绑定onClick) - 直接调用
props.RemoveList(index)会导致组件渲染时立即执行setState,触发跨组件更新警告
修改ToDoList.js中的移除按钮代码:
<button className="btn btn-danger" onClick={() => props.RemoveList(index)}>Remove</button>
2. 修复列表项缺少唯一key的警告
React列表渲染要求每个子项有唯一key属性,避免使用index作为key(列表增删时index会变化,可能引发渲染异常),建议给每个todo对象添加唯一ID:
步骤1:在Todo.js的addNew函数中添加唯一ID
function addNew(addText, date){ const obj = { id: Date.now(), // 生成唯一ID text : addText, expiry : date, completed : false } const newToDo = [...toDoList, obj]; setToDoList(newToDo); }
步骤2:在ToDoList.js的map循环中添加key属性
注意:React.Fragment(<>)不能添加key,需直接将<li>作为根元素并设置key:
{props.list.map((element, index) => { return ( <li key={element.id} // 使用唯一ID作为key className={ element.completed ? "list-group-item yes-comp" : "list-group-item no-comp" } > <span className="badge text-bg-info">{index + 1}</span>   <input type="checkbox" defaultChecked={element.completed} onChange={() => { props.handleCheck(index); }} />{" "}   {element.text} <span className="badge text-bg-light"> {element.expiry.toString().slice(4, 15)} </span> <button className="btn btn-danger" onClick={() => props.RemoveList(index)}>Remove</button> </li> ); })}
如果暂时不想添加ID,也可以先用index作为key(不推荐长期使用):
<li key={index} ...>...</li>
内容的提问来源于stack exchange,提问作者Fenil Patel
相关产品推荐
相关产品推荐

