Md. Irfan Omee
Md. Irfan Omee

Reputation: 73

I can't figure out why setState function not working for setting a value

Hope you are all well and healthy. I am learning react and following a tutorial : https://www.youtube.com/watch?v=DLX62G4lc44&t=9947s Time is also mentioned in YouTube video where I got stuck. This is my Code:

This is the ToDoComponent

import React from 'react';

function ToDoItem(props){
    return(
        <div className="tasks">
            <label>{props.item.taskName}</label><input type="checkbox" 
            checked={props.item.completed} onChange={() => props.handleChange(props.item.Id)}/> 
        </div>  
    );
}


export default ToDoItem;

And This is the App.js

import React, { Component } from 'react';
import './App.css';
import ToDoItem from './components/ToDoItem';
import toDoData from './datas/tododata';


class App extends Component{
  constructor(){
    super();
    this.state = {todos : toDoData}
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(Id){
    this.setState(prevState => {
      
      const updatedToDos = prevState.todos.map(todo => {
        if(todo.Id == Id){
          console.log(todo.completed)
          todo.completed = !todo.completed 
          console.log(todo.completed)
        }
        return todo
      })
      
      return{
        todos : updatedToDos
      }
        
    })


  }

  render(){
    var toDoComponent = this.state.todos.map(
      item => 
        <ToDoItem key={item.Id} item={item} handleChange={this.handleChange}/>
      );

    return(
      <div>
        {toDoComponent}
      </div>
    );
  }
}


export default App;

Now look at this picture. When I click the CheckBox, the setState is called twice and the CheckBox value is not changing because of that. enter image description here I can't find where the problem is.

Upvotes: 0

Views: 41

Answers (1)

JLRishe
JLRishe

Reputation: 101730

It sounds like you are using React's strict mode, which causes setState updater functions, and other lifecycle functions, to be called twice in order to test whether these functions are actually pure, as they should be.

It seems the problem here is that you are mutating your state, on this line:

todo.completed = !todo.completed 

Here, you are modifying an object that is part of the previous state. So you are modifying the previous state when you should only be creating a new state and leaving the previous one alone.

Strict mode is intended to identify these kinds of problems.

To solve this, make sure that your setState updater does not mutate the state:

const updatedToDos = prevState.todos.map(todo => {
    if(todo.Id == Id){
        console.log(todo.completed)
        const newTodo  = { ...todo, completed: !todo.completed }
        console.log(newTodo.completed)
        return newTodo;
    }

    return todo
})

Upvotes: 2

Related Questions