code_dude
code_dude

Reputation: 1111

How can I make the currently selected todo get updated with the modified value?

I am making a todo app to sharpen my react skills with hooks and I want to make a function updateTask to update the currently selected task with whatever I type in the input after the getCurrentTask function is triggered, which populates the input value with the currently selected task's text value.

This is the updateTask function:

function updateTask(statePlaceholder, id) {
  const updatedTaskIndex = statePlaceholder.tasks.findIndex(
    task => task.id === id
  );
  const updatedTask = statePlaceholder.tasks.map(task => {
    return { ...task, text: statePlaceholder.currentTask.text };
  });
  const updatedTasks = [
    ...statePlaceholder.tasks.slice(0, updatedTaskIndex),
    updatedTask,
    ...statePlaceholder.tasks.slice(updatedTaskIndex + 1)
  ];

  return {
    ...statePlaceholder,
    tasks: updatedTasks,
    currentTask: null
  };
}

and I use this function in the handleSubmit function in the form

function handleSubmit(e) {
    e.preventDefault();

    state.currentTask
      ? setState(updateTask(state, state.currentTask.id))
      : setState(createTask(state, value));

    setValue("");
  }

I want to be able to update the currently selected task.

Upvotes: 0

Views: 398

Answers (2)

ckedar
ckedar

Reputation: 1909

There are is an error in your updateTask function, but before coming to that there is a suggestion.

Looks like you are using composite state, like

[state, setState] = useState({tasks:[], current:0})

Instead more idiomatic way is to use separate state variables:

[tasks, setTasks] = useState([]);
[current, setCurrent] = useState(0);

This will also make your state management much more easier.

Now coming back to error in updateState, after retrieving updatedTaskIndex, you need to 1) retrieve the originalTask, 2) mutate it and 3) put it back in right position in new array. You are not doing #1 and hence #2 you are attempting will produce wrong result. Do something like

origTask = tasks[taskIndex];
updatedTask = {...origTask, text: text}

Upvotes: 1

Tal Avissar
Tal Avissar

Reputation: 10304

The logic of your code is basically returning a collection of updates tasks.

And then the problem is that you're having duplicate keys in your statePlaceholder.tasks list

Why you need to replace the text in all your statePlaceholder.tasks,

It seems that you are returning an array here (many tasks and not just one task) so this causes later on the duplicate keys error

 const updatedTask = statePlaceholder.tasks.map(task => {
    return { ...task, text: statePlaceholder.currentTask.text };
  });

its better that change to:

      const updatedTask = statePlaceholder.tasks.filter(task => task.id === id)
      updatedTask.text= statePlaceholder.currentTask.text;

      const updatedTasks = [
        ...statePlaceholder.tasks.slice(0, updatedTaskIndex),
        updatedTask,
        ...statePlaceholder.tasks.slice(updatedTaskIndex + 1)
      ];

so I looked at your code posted at the sandbox and the problem is that function updateTask(statePlaceholder, id)

parameter id is arriving as undefined, and then updatedTaskIndex -> -1

You are only setting the name of the task and not the object(with the id) here:

  <input
        type="text"
        className="App_input"
        placeholder="Type Task"
        value={value}
        onChange={e => setValue(e.target.value)}
      />

Upvotes: 0

Related Questions