skip to Main Content

I am stuck for 1 full day on this. I want when the checkbox is checked, the value of ‘Done’ changes as planned below. Please help me as I am learning this. Tried using usestate but it cant work. The method I used below is a mutable method and I learnt it doesnt work in react. I tried using setTodo to set the object but it gives an entirely diferent thing. Here is the link to the code: https://codesandbox.io/s/serene-lederberg-39ub6v?file=/src/App.js

Below is my code:

import "./styles.css";
import {useState} from 'react'
import Addtask from './Addtask'

export default function App() {

 
  const dataset = [
                  {key:'', id: 1, title: 'Go to School', done: 'false'},
                  {key:'', id: 2, title: 'Go to Gym house', done: 'false'},
                  {key:'', id: 3, title: 'Go to Market', done: 'false'},
                  {key:'', id: 4, title: 'Go to Stadium', done: 'false'},
                  {key:'', id: 5, title: 'Go to Podium', done: 'false'},
                ]

  const [todos, setTodos] = useState(dataset)
  const [todo, setTodo] = useState('')


  
  const todolist = todos.map(singletodo => {

      return (
        
        <ul style={{paddingBottom: '1em'}}>
        <li> 
        <span><input type='checkbox'  
        onChange={(e) =>  {
          if(e.target.checked){
          alert('hello')
          singletodo["done"] = 'true'
          }else {
            alert('nooooo')
            singletodo["done"] = 'false'

          }
      }  }/><label> Completed </label>

        </span>
        </li>
        <li>Title: {singletodo.title}</li>
        <li>ID: {singletodo.id}</li>

        <li>Done: {singletodo.done}</li>
       <hr></hr><li> <button onClick ={()=> setTodos(todos.filter(bad => bad.key !==singletodo.key))} style={{float: 'left', }}>delete</button> 
       
        <button style={{float: 'right',}}>edit</button></li>
        </ul>)
 
  });


  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>

      <Addtask data ={todo} list = {todos} settodo = {setTodo} settodos ={setTodos}/>
      {todolist}

    </div>
  );
}

2

Answers


  1. In React, when you want to update an array that is being tracked in state, you not only need to update the array, but also call setTodos on it.

    Once you’ve updated the array itself with the changes you want to make(inside the onChange). Then, you need to call the setTodos method and pass in the updated array as a parameter.

    if (e.target.checked) {
      alert('hello');
      singletodo["done"] = 'true';
    } else {
      alert('nooooo');
      singletodo["done"] = 'false';
    }
    setTodos(prevTodos => {
      const updatedTodos = prevTodos.map(todo => {
        if (todo.id === singletodo.id) {
          return singletodo;
        }
        return todo;
      });
      return updatedTodos;
    });
    
    
    Login or Signup to reply.
  2. i edited your code :

    import "./styles.css";
    import { useState } from "react";
    
    export default function App() {
      const dataset = [
        { key: "", id: 1, title: "Go to School", done: "false" },
        { key: "", id: 2, title: "Go to Gym house", done: "false" },
        { key: "", id: 3, title: "Go to Market", done: "false" },
        { key: "", id: 4, title: "Go to Stadium", done: "false" },
        { key: "", id: 5, title: "Go to Podium", done: "false" }
      ];
    
      const [todos, setTodos] = useState(dataset);
    
      const setDoneForTodo = (isDone, index) => {
        setTodos((todos) =>
          todos.map((todo, i) => {
            if (index === i) {
              return { ...todo, done: isDone ? "true" : "false" };
            } else {
              return todo;
            }
          })
        );
      };
    
      const todolist = todos.map((singletodo, index) => {
        return (
          <ul style={{ paddingBottom: "1em" }} key={index}>
            <li>
              <span>
                <input
                  type="checkbox"
                  onChange={(e) => {
                    if (e.target.checked) {
                      setDoneForTodo(true, index);
                    } else {
                      setDoneForTodo(false, index);
                    }
                  }}
                />
                <label> Completed </label>
              </span>
            </li>
            <li>Title: {singletodo.title}</li>
            <li>ID: {singletodo.id}</li>
    
            <li>Done: {singletodo.done}</li>
            <hr></hr>
            <li>
              {" "}
              <button
                onClick={() =>
                  setTodos(todos.filter((bad) => bad.key !== singletodo.key))
                }
                style={{ float: "left" }}
              >
                delete
              </button>
              <button style={{ float: "right" }}>edit</button>
            </li>
          </ul>
        );
      });
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          {todolist}
        </div>
      );
    }
    

    please check this link

    you need use setState for updating state ,
    in this case use setTodos for todos state! :

    const setDoneForTodo = (isDone, index) => {
        setTodos((todos) =>
          todos.map((todo, i) => {
            if (index === i) {
              return { ...todo, done: isDone ? "true" : "false" };
            } else {
              return todo;
            }
          })
        );
      };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search