Shadov
Shadov

Reputation: 33

React setState not updating the state

I'm new to React and I'm having some trouble with changing sate with setState method. I'm trying to update state of ToDo item when I click on the checkbox. When I'm debugging handleChange method it changes the state of the item for a while. Unfortunatelly, the final state is like at the beginning (state of the checkbox is never changed). Does somebody know where the problem is?

class App extends React.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} todoItem={item} 
    handleChange={this.handleChange}/>) 

  return (
       <div className="App">
         {todoItems}
       </div>
   );
}

}

export default App;

Here is my ToDoItem component:

import React from 'react'

function ToDoItem(props){
    return (
        <div className = "todo-list">
            <div className = "todo-item">
                <input type="checkbox" 
                    checked={props.todoItem.completed} 
                    onChange = {() => props.handleChange(props.todoItem.id)}/>
                <p>{props.todoItem.text}</p>
            </div>
        </div>
    )
}

export default ToDoItem

Upvotes: 0

Views: 155

Answers (2)

Daniel Lazar
Daniel Lazar

Reputation: 111

Just use this handler and let me know if works.

handleChange(id){
    const list = this.state.todos.slice();
    const index = list.findIndex(o => o.id === id);
    list[index].completed = !list[index].completed;
    this.setState({ todos: list });
}

Upvotes: 1

Diyorbek Sadullaev
Diyorbek Sadullaev

Reputation: 477

I think the problem is here:

   handleChange(id){
     this.setState(prevState => {
        const updatedTodos = prevState.todos.map(todo => {
           if (todo.id === id) {
               todo.completed = !todo.completed
           }
           return { ...todo }; // need to return a new object
        })
        return {
            todos: updatedTodos
        }
      })
    }

todos are objects and event if todos are being set as a new object every time, its items referencing to the same object, and it is used by ToDoItem.

Upvotes: 0

Related Questions