[英]Checkbox not changing state in React component
我正在使用 React 創建一個 todolist 應用程序。 待辦事項的數據如下所示:
const todoData = [
{
id: 1,
text: "Empty bin",
completed: true
},
{
id: 2,
text: "Call mom",
completed: false
}
]
現在,我有一個 App 組件,我可以在其中導入該數據並將其保存在狀態中。
import todoData from "./todoData"
class App extends React.Component {
constructor() {
super()
this.state = {
todos: todoData,
}
this.handleChange = this.handleChange.bind(this)
}
...
我還有一個 handleChange 方法,它應該將完成的屬性的值更改為其相反的值。 例如:對於 id 為 1 的待辦事項,它的文本值為“Empty Bin”,並且已完成為 true,因此默認情況下將選中復選框。 但是,當它被點擊時,完成應該是假的,並且不再點擊復選框。 出於某種原因,這不會發生,因此完成保持其默認布爾值並且不會翻轉。 因此,當單擊復選框時不會發生任何變化。
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todos: updatedTodos
}
})
}
使用 console.log 后,我意識到 todo.completed 確實被更改為其相反的值,但由於某種原因,它沒有在 updatedTodos 中更改,即使在 devtools map() 中說當它返回一個新數組時該值已更新存儲在 updatedTodos 中。 因此,狀態不會改變並且無法單擊復選框
TodoItem 功能組件與 App 組件位於一個單獨的文件中,並包含 todo 元素的 HTML。 如下圖所示:
function TodoItem(props) {
return (
<div className="todo-item">
<input type="checkbox"
checked={props.task.completed}
onChange={() => props.handleChange(props.task.id)}/>
<p>{props.task.text}</p>
</div>
)
}
此外,TodoItem 是在 App 組件中呈現的
render() {
const todoArray = this.state.todos.map(task => <TodoItem key={task.id}
task={task} handleChange={this.handleChange}/>)
return (
<div className="todo-list">
{todoArray}
</div>
)
}
看起來你正在改變handleChange
函數中的 todo 對象
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
//todo.completed = !todo.completed this is mutating
// in react mutating a object will result in unexpected results like this.
// so you have to create a new object based on the current todo and return it
return {
...todo,
completed: !todo.completed
}
}
return todo
})
return {
todos: updatedTodos
}
})
}
那里發生了什么?
數組中的每個對象都指向一個內存位置,基本上,如果我們更改對象屬性值(例如: completed
),而不更改它正在變異的內存位置,
並通過這樣做todo.completed = !todo.completed
我們直接改變的值completed
屬性,但仍指向同一個內存位置的待辦事項對象,所以我們做這個變異的對象,反應也不會對此作出回應,現在
return {
...todo, // <- create a new object based on todo
completed: !todo.completed // <- change the completed property
}
我們創建基於待辦事項的新對象{...todo}
(新對象=新的存儲位置),和我們改變的值completed
=> {...todo, completed: !todo.completed}
因為這是指向新的內存位置 react 會響應變化。
如果您不熟悉擴展運算符 ( ...
),請在此處閱讀,不要忘記查看那里的對象文字部分中的擴展
你需要傳播你的對象然后改變特定的領域
if (todo.id === id) {
return {
...todo,
completed: !todo.completed
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.