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

React待办列表移除按钮失效及控制台警告问题求助

React Todo List移除按钮失效及控制台警告修复

问题现象

  • 为Todo List添加移除功能后,移除按钮无法正常工作;移除该功能后,其他模块运行正常
  • 控制台抛出两个警告:
    1. react-dom.development.js:86 Warning: Cannot update a component (Todo) while rendering a different component (ToDoList).
    2. 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> &ensp;
              <input
                type="checkbox"
                defaultChecked={element.completed}
                onChange={() => {
                  props.handleCheck(index);
                }}
              />{" "}
              &ensp;
              {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> &ensp;
      <input
        type="checkbox"
        defaultChecked={element.completed}
        onChange={() => {
          props.handleCheck(index);
        }}
      />{" "}
      &ensp;
      {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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:30:58