Answer the question
In order to leave comments, you need to log in
Why doesn't the state of a component change in React?
Hello, I don’t understand why the state of the checkboxes does not change when clicked, the most interesting thing is that if you replace todo.completed with todo.text and change the text, then the state will be changed, also if you add console.log("Clicked", id), then it will output the word Clicked and the id of the checkbox. I would be very happy if you help me figure it out.
Here is the parent component code:
import React, { Component } from 'react'
import TodoItem from "./TodoItem"
import todosData from "./todosData"
class App extends Component {
constructor() {
super()
this.state = {
todos: todosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todos: updatedTodos
}
})
}
render() {
const todoItems = this.state.todos.map(item => <TodoItem key={item.id} item={item} handleChange={this.handleChange}/>)
return (
<div className="todo-list">
{todoItems}
</div>
)
}
}
export default App
import React from "react"
function TodoItem(props) {
return (
<div className="todo-item">
<input
type="checkbox"
checked={props.item.completed}
onChange={() => props.handleChange(props.item.id)}
/>
<p>{props.item.text}</p>
</div>
)
}
export default TodoItem
const todosData = [
{
id: 1,
text: "Take out the trash",
completed: true
},
{
id: 2,
text: "Grocery shopping",
completed: false
},
{
id: 3,
text: "Clean gecko tank",
completed: false
},
{
id: 4,
text: "Mow lawn",
completed: true
},
{
id: 5,
text: "Catch up on Arrested Development",
completed: false
}
]
export default todosData
Answer the question
In order to leave comments, you need to log in
The string
todo.completed = !todo.completed
is executed twice on each click, so first the value becomes false, then true again, while the text variable changes nicely. I'm a little ashamed, because I don't know exactly how the react works in this case, but there are two ways out:
1)
if (todo.id === id) return { ...todo, completed: !todo.completed }
return todo
onChange={() => props.handleChange(props.item.id, !props.item.completed)}
handleChange(id, newCompleted) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = newCompleted
}
return todo
})
return {
todos: updatedTodos
}
})
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed }
}
return todo
})
return {
todos: updatedTodos
}
})
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question