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

ReactJS中如何在Checkbox变更时实时同步Done值

React中Checkbox勾选后无法更新Done状态的解决方案

问题核心

你当前的代码存在三个关键问题:

  1. 直接修改singletodo对象的done属性,属于直接变更React State,违反了不可变更新原则,React无法检测到这种修改,组件不会重渲染,导致Done值不更新。
  2. 修改状态后没有调用setTodos触发状态更新,即便修改了对象,组件也不会同步视图。
  3. done字段使用字符串'true'/'false',不符合checkbox布尔值状态的逻辑习惯。

解决步骤

  1. 修正初始数据类型:将done字段从字符串改为布尔值true/false,匹配checkbox的状态逻辑。
  2. 实现不可变状态更新:通过创建新数组的方式修改目标todo的done状态,再调用setTodos更新。
  3. 同步Checkbox视图与数据:给input的checked属性绑定singletodo.done,确保视图和数据一致。
  4. 修复删除逻辑:用唯一的id替代空字符串key作为过滤条件,保证删除功能正常。

修改后的完整代码

import "./styles.css";
import { useState } from 'react'
import Addtask from './Addtask'

export default function App() {
  // 修正done为布尔值
  const dataset = [
    { key:'', id: 1, title: 'Go to School', done: false },
    { key:'', id: 2, title: 'Go to Gym house', done: false },
    { key:'', id: 3, title: 'Go to Market', done: false },
    { key:'', id: 4, title: 'Go to Stadium', done: false },
    { key:'', id: 5, title: 'Go to Podium', done: false },
  ]

  const [todos, setTodos] = useState(dataset)
  const [todo, setTodo] = useState('')

  // 统一处理Checkbox状态变更
  const handleCheckboxChange = (todoId, isChecked) => {
    // 不可变更新:生成新数组,仅修改目标todo的done状态
    setTodos(prevTodos => 
      prevTodos.map(todo => 
        todo.id === todoId ? { ...todo, done: isChecked } : todo
      )
    )
  }

  const todolist = todos.map(singletodo => {
    return (
      // 给列表项添加唯一key
      <ul key={singletodo.id} style={{paddingBottom: '1em'}}>
        <li> 
          <span>
            {/* 绑定checked属性,同步数据与视图 */}
            <input 
              type='checkbox'  
              checked={singletodo.done}
              onChange={(e) => handleCheckboxChange(singletodo.id, e.target.checked)}
            />
            <label> Completed </label>
          </span>
        </li>
        <li>Title: {singletodo.title}</li>
        <li>ID: {singletodo.id}</li>
        {/* 布尔值转字符串显示 */}
        <li>Done: {singletodo.done ? 'true' : 'false'}</li>
        <hr />
        <li> 
          {/* 用id作为删除的过滤条件 */}
          <button 
            onClick={() => setTodos(todos.filter(item => item.id !== singletodo.id))} 
            style={{float: 'left'}}
          >
            delete
          </button> 
          <button style={{float: 'right'}}>edit</button>
        </li>
      </ul>
    )
  })

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Addtask data={todo} list={todos} settodo={setTodo} settodos={setTodos}/>
      {todolist}
    </div>
  )
}

关键说明

  • 不可变更新:使用prevTodos.map创建新数组,对目标todo通过扩展运算符{...todo, done: isChecked}生成新对象,确保React能检测到状态变化并触发重渲染。
  • 状态与视图同步:checked={singletodo.done}让Checkbox的显示状态始终和数据保持一致,避免出现数据和视图脱节的情况。
  • 唯一标识:用id作为列表项的key和删除过滤条件,保证组件渲染和功能逻辑的稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 06:30:05