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时刚好和初始值不同,后续再切换也会失效
- map遍历拿到的
修复方案
修改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
相关产品推荐
相关产品推荐

