我正在使用reactjs创建一个todo应用程序,并且当用户单击输入时我试图更新我的todo项目列表。当用户单击时,我可以更改该项目,但该项目的状态不会更新。我不明白为什么状态不更新。我认为这与 .map() 并将 todo 对象返回到新数组有关,但我不太清楚出了什么问题。有什么想法吗?
应用程序.js
import React from 'react'
import TodoItem from './components/TodoItem'
import TodosData from './TodosData'
import './App.scss'
class App extends React.Component {
constructor() {
super()
this.state = {
todoItems: TodosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState( prevState => {
const updatedTodos = prevState.todoItems.map( todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todoItems: updatedTodos
}
})
}
render() {
const todosComponents = this.state.todoItems.map( item => {
return <TodoItem key={item.id} todo={item} handleChange={this.handleChange}/>
})
return (
<div className="TodoList">
{todosComponents}
</div>
)
}
}
export default App;
TodosItem.js
import React from 'react'
function TodoItem(props) {
return (
<div className="TodoItem">
<input
type="checkbox"
checked={props.todo.completed}
onChange={ () => props.handleChange(props.todo.id) }
/>
<p>{props.todo.text}</p>
</div>
)
}
export default TodoItem
你正在改变你的状态对象。由于嵌套对象引用是相同的,React 会阻止渲染任何可能已更新的内容。换句话说,由于对象引用与之前的渲染相同,React 假设没有任何变化。
handleChange(id) {
this.setState( prevState => {
const updatedTodos = prevState.todoItems.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed // <-- object mutation!!
}
return todo
})
return {
todoItems: updatedTodos
}
})
}
除了浅复制数组之外,您还需要浅复制正在更新的任何嵌套状态。
handleChange(id) {
this.setState( prevState => {
const updatedTodos = prevState.todoItems.map(todo => {
if (todo.id === id) {
return {
...todo // <-- copy todo
completed: !todo.completed, // <-- update propety
}
}
return todo
})
return {
todoItems: updatedTodos
}
})
}