Nick
Nick

Reputation: 674

update useState() array when element is modified REACT

I am fairly new to react to please bare with me. I am creating a todo application that just keeps tracks of tasks.

Issue:

the state called [tasks, setTasks] = useState([]) does update when i try to edit a task within the tasks state.

For example lets say tasks contains ["make bed", "fold cloths"] and I wanted to update "fold cloths" to "fold clothes and put away". When I use setTasks the state does not update.

The modification of the state happens in the modifyTask function.

Here is my code:

import React, { useEffect, useState } from "react";

// Imported Components below
import CurrentTasks from "./CurrentTasks";

function InputTask() {
  // Initial array for storing list items
  // Tracking state of input box
  const [task, setTask] = useState("");
  const [tasks, setTasks] = useState(
    JSON.parse(localStorage.getItem("tasks") || "[]")
  );

  function deleteTask(index) {
    function checkIndex(task, i) {
      if (i !== index) {
        return task;
      }
    }
    setTasks(prev => prev.filter(checkIndex));
  }

  function modifyTask(index) {
    let editedTask = prompt("Please edit task here..", tasks[index]);
    function editTask(task, i) {
      if (i === index) {
        task = editedTask;
      }
      console.log(task);
      return task;
    }
    setTasks(prev => prev.filter(editTask));
  }

  function handleAddTask() {
    setTasks(prev => prev.concat(task));
  }

  useEffect(() => {
    // Saves every time tasks state changes
    localStorage.setItem("tasks", JSON.stringify(tasks));
    console.log("Tasks: " + tasks);
    setTask("");
  }, [tasks]);

  return (
    <div className="container">
      <div className="input-group mt-4">
        <input
          type="text"
          value={task}
          onChange={e => setTask(e.target.value)}
          className="form-control form-control-lg"
          placeholder="Write task here..."
        />
        <div className="input-group-append">
          <button onClick={handleAddTask} className="btn btn-outline-secondary">
            Add
          </button>
        </div>
      </div>
      <CurrentTasks
        allTasks={tasks}
        deleteTask={deleteTask}
        modifyTask={modifyTask}
      />
    </div>
  );
}

export default InputTask;

What I think is happening

-> My theory is that the state only updates when the number of elements within the array changes. If thats the case is there an elegant way of doing so?

enter image description here

Upvotes: 0

Views: 487

Answers (1)

Zachary Haber
Zachary Haber

Reputation: 11027

You just need to change your modify function to use map instead of filter, as filter doesn't change the array outside of removing elements. Map takes the returned values and creates a new array from them.

  function modifyTask(index) {
    let editedTask = prompt("Please edit task here..", tasks[index]);
    function editTask(task, i) {
      if (i === index) {
        task = editedTask;
      }
      console.log(task);
      return task;
    }
    setTasks(prev => prev.map(editTask));
  }

Upvotes: 2

Related Questions