我是react.js的新手。我正在youtube上学习react.js的视频。我在简单的事件处理工作,并在一些问题卡住。当用户在复选框上执行onclick功能时,我想选中/取消选中复选框。但不知何故,返回的数组没有更新,复选框也不可操作。我将我的代码粘贴到下面:
App.js
import React from 'react'
import Header from './components/Header'
import Todolist from './components/Todolist'
import todosData from './data/todosData'
class App extends React.Component {
constructor(){
super()
this.state = {
todos: todosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id){
this.setState(prevState => {
console.log(prevState.todos)
const updatedTodos = prevState.todos.map(todo => {
if(todo.id === id){
todo.completed = !todo.completed
}
return todo
})
console.log(updatedTodos)
return{
todos : updatedTodos
}
})
}
render(){
const todoItems = this.state.todos.map(item => <Todolist key={item.id} item={item} handleChange={this.handleChange} />)
return (
<div>
<Header />
{todoItems}
</div>
)
}
}
export default App;
TodoList.js
import React from 'react'
function Todolist(props){
return(
<div className='todo-item'>
<input type='checkbox'
checked={props.item.completed}
onChange={() => props.handleChange(props.item.id)}
/>
<span>{props.item.text}</span>
</div>
)
}
export default Todolist
您试图在这一行改变数组的原始项/对象!
todo.completed = !todo.completed
您可以尝试使用Object.assign
或使用spread创建一个新对象。两种方式都可以,但传播方式更可取。
使用Object.assign
handleChange(id) {
this.setState((prevState) => {
const updatedTodos = prevState.todos.map((todo) => {
// Object.assign creates a new object!
const changedTodo = Object.assign({}, todo, {
completed: todo.id === id ? !todo.completed : todo.completed
});
return changedTodo;
});
return {
todos: updatedTodos
};
});
}
使用扩展...
handleChange(id) {
this.setState((prevState) => {
const updatedTodos = prevState.todos.map((todo) => {
const changedTodo = {
...todo,
completed: todo.id === id ? !todo.completed : todo.completed
};
return changedTodo;
});
return {
todos: updatedTodos
};
});
}
如前所述,setState
在严格模式下运行两次。使用相同的输入调用状态更新器函数两次。这应该是好的,并产生相同的输出。但这里的问题是您重用了todo
对象,而不是创建一个新对象。这反过来又导致completed
标志被翻转两次。
你可以修改你的updatater函数,每次创建一个新的todo对象:
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
return {
...todo,
completed: !todo.completed,
};
}
return todo;
});
return {
todos: updatedTodos,
};
});