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

React应用Todo项无法切换完成/未完成状态的问题求助

问题根因

  • 核心问题是你直接修改了state中原todo对象的属性,违反了React状态不可变的原则:
    • map遍历拿到的todo是prevState.todos数组里的原对象引用,直接执行todo.completed = !todo.completed属于直接修改原状态,没有生成新的对象
    • 如果你的TodoItem组件用了React.PureComponent或者被React.memo包裹,新旧todo对象的引用完全一致,浅层比较时会判定属性没有变化,不会触发重新渲染,所以看不到状态切换效果
    • 固定赋值false能生效属于巧合:大概率是你初始todosData里所有todo的completed默认都是true,第一次修改为false时刚好和初始值不同,后续再切换也会失效

修复方案

修改handleChange里的逻辑,匹配到对应id时返回全新的todo对象,不修改原对象即可:

handleChange(id) {
    this.setState(prevState => {
        const updatedTodos = prevState.todos.map(todo => {
            if (todo.id === id) {
                // 展开原属性,覆盖completed字段,返回新对象
                return {
                    ...todo,
                    completed: !todo.completed
                }
            }
            return todo
        })
        return {
            todos: updatedTodos
        }
    })
}

React Hooks版本实现参考

import React, { useState } from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"
import './styles.css'

function App() {
    const [todos, setTodos] = useState(todosData)
    
    const handleChange = (id) => {
        setTodos(prevTodos => {
            return prevTodos.map(todo => {
                if (todo.id === id) {
                    return {
                        ...todo,
                        completed: !todo.completed
                    }
                }
                return todo
            })
        })
    }
    
    const todoItems = todos.map(item => <TodoItem key={item.id} item={item} handleChange={handleChange}/>)
    
    return (
        <div className="todo-list">
            {todoItems}
        </div>
    )
}

export default App

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:45:05