skip to Main Content

I’m making simple todo list in react, and when i delete a task it doesnt update immediately, but when i make a change in input, I don’t know why it happens. Tried to change how deleteTask works but i didnt found the solution.

form.jsx

import { useState } from 'react';
import './styles/form.css';
import Tasks from './tasks';

function TaskForm() {
  const initialList = [{task: 'Do something', done: false}];
  const [tasks, setTasks] = useState(initialList);
  const [input, setInput] = useState('');
  const [validTask, setValidTask] = useState('valid');
  const addTask = () => {
    if(input.length !== 0) {
      setValidTask('valid');
      setTasks(tasks.push({task: input, done: false}));
      setTasks(tasks);
      setInput('');
    }
    else {
      setValidTask('invalid');
    }
    console.log(tasks);
  }
  return (
    <>
      <div className='maindiv'>
        <p>Task app</p>
        <input maxLength={32} value={input} placeholder='add a new task...' onChange={e => setInput(e.target.value)}/><br />
        <p style={{color: 'red'}} className={validTask}>Task can't be empty</p>
        <input type='submit' value='Add task' onClick={addTask}/>
      </div>
      <Tasks tasks={tasks}/>
    </>
  );
}

export default TaskForm;

tasks.jsx

import { useState } from 'react';
function Tasks(props) {
  const [tasks, setTasks] = useState(props.tasks);
  const deleteTask = (index) => {
    tasks.splice(index, 1);
    setTasks(tasks);
    
  };
  const taskList = props.tasks.map(task => (
    <li key={task.id}>
      <input type='checkbox' value={task.done} /> 
      {task.task}
      <input type='button' value='delete' onClick={() => deleteTask(task.id)} />
    </li>
  ));
  return <ul>{taskList}</ul>;
}

export default Tasks;

2

Answers


  1. You can’t splice arrays in React states as clearly described in the docs

    const deleteTask = (index) => {
        setTasks(tasks => [...tasks.slice(0, index), ...tasks.slice(index+1)]);
    };
    

    or using filter:

    const deleteTask = (index) => {
        setTasks(tasks => [...tasks].filter((_, i) => i === index));
    };
    
    Login or Signup to reply.
  2. You’re not updating state, you’re mutating state:

    tasks.splice(index, 1);
    setTasks(tasks);
    

    According to the documentation:

    The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.

    So instead of creating a new array reference, you’re modifying the existing array reference and setting state back to that same reference. Since the reference doesn’t change, React doesn’t see that the state was "updated". Which is why mutating state leads to bugs like this.

    Create a new array reference, modify that, then update state to that:

    let newTasks = [...tasks];
    newTasks.splice(index, 1);
    setTasks(newTasks);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search