React待办列表检测checkbox全选并触发console.log问题求解
你代码里的核心问题如下:
- 冗余的
checked状态:你定义的const [checked, setChecked] = useState(false)是布尔值,不是存储选中项的数组,自然无法通过.length拿到选中数量,而且你所有选中状态实际存储在todos数组每个元素的completed字段中,这个状态完全没用可以删掉。 - 对比逻辑错误:你在
allChecked里对比的todo.length是当前输入框内的文本长度,不是总待办数量,总待办数量应该取todos.length。 - 取值错误:你调用
allChecked时传入的todo.checked不存在,每个待办的选中状态存在todo.completed字段。 - 异步更新问题:React的
setState是异步执行的,你在调用toggleCompleteToDo修改todos后立即读取todos拿到的还是旧值,直接判断会有逻辑偏差。
正确实现步骤:
- 先导入
useEffect钩子,用来监听todos数组的变化,自动判断是否全选 - 删掉无用的
checked状态 - 新增监听
todos的useEffect,在里面统计已选中的待办数量,和总待办数对比即可
修正后的完整代码:
import React from 'react'; import { AiOutlinePlusCircle } from 'react-icons/ai'; import { useState, useEffect } from 'react'; function Checkboxes() { const [todo, setToDo] = React.useState(''); const [todos, setToDos] = React.useState([]); function handleToDoSubmit(e) { e.preventDefault(); const newToDo = { id: new Date().getTime(), text: todo, completed: false, }; setToDos([...todos].concat(newToDo)); setToDo(''); } function toggleCompleteToDo(id) { const updatedToDos = [...todos].map((todo) => { if (todo.id === id) { todo.completed = !todo.completed; } return todo; }); setToDos(updatedToDos); } // 监听todos变化自动判断全选 useEffect(() => { // 过滤已完成待办,长度就是已勾选数量 const checkedCount = todos.filter(item => item.completed).length; // 加todos.length>0判断避免无待办时误触发 if (todos.length > 0 && checkedCount === todos.length) { console.log("all checked"); } }, [todos]) return ( <div className="ToDoList"> <form className="goalInputToDo" onSubmit={handleToDoSubmit}> <input className="goalInput" type="text" onChange={(e) => setToDo(e.target.value)} value={todo} /> <button className="AddGoalBtn" type="submit"> . <AiOutlinePlusCircle size="2em" /> </button> </form> {todos.map((todo) => ( <div className="goalItem"> <div key={todo.id}> <div>{todo.text}</div> <input type="checkbox" onChange={() => toggleCompleteToDo(todo.id)} checked={todo.completed} /> </div> </div> ))} </div> ); } export default Checkboxes;
内容的提问来源于stack exchange,提问作者RJL
相关产品推荐
相关产品推荐

