Удаление определенного элемента из массива в React с использованием функциональных компонентов / перехватов

#reactjs #react-hooks #react-functional-component

#reactjs #реагирующие перехваты #react-functional-component

Вопрос:

Я пытаюсь удалить элемент в массиве. Однако моя кнопка удаления не выполняет мой код, и массив остается неизменным. Я не уверен, что делать.

Мой код приведен ниже:

 //App.js

import React, { useState } from "react";
import Overview from "./components/Overview";

function App() {
  const [task, setTask] = useState("");
  const [tasks, setTasks] = useState([]);

  function handleChange(e) {
    setTask(e.target.value);
  }

  function onSubmitTask(e) {
    e.preventDefault();
    setTasks(tasks.concat(task));
    setTask("");
  }

  //error happening here????---------------------------------------------------
  function removeTask(itemId) {
      setTasks(prevState => prevState.filter(({ id }) => id !== itemId));
  }


  return (
    <div className="col-6 mx-auto mt-5">
      <form onSubmit={onSubmitTask}>
        <div className="form-group">
          <label htmlFor="taskInput">Enter task</label>
          <input
            onChange={handleChange}
            value={task}
            type="text"
            id="taskInput"
            className="form-control"
          />
        </div>
        <div className="form-group">
          <button type="submit" className="btn btn-primary">
            Add Task
          </button>
        </div>
      </form>
      <Overview tasks={tasks} removeTask={removeTask} />
    </div>
  );
}

export default App;
 

Дочерний компонент:

 import React from "react";

function Overview(props) {
  const { tasks, removeTask } = props;
  console.log(tasks)
  return (
    <>
      {tasks.map((task, index) => {
        return (
          <>
            <p key={index}>
              #{index   1} {task}
            </p>
            //this onClick isn't doing anything-------------------------------------
            <button onClick={() => removeTask(index)}>Delete Task</button>
          </>
        );
      })}
    </>
  );
}
export default Overview;
 

Мое состояние «задачи» дает мне массив с элементами внутри в виде строк. Однако, когда я попытался отфильтровать массив, это не сработало. Поэтому вместо фильтрации по значению я попытался фильтровать по идентификатору / индексу. Поскольку индекс будет соответствовать ему, я подумал, что это удалит элемент из массива, даже если есть только один элемент, он ничего не удаляет, а кнопка удаления просто регистрирует в консоли данный массив.

Любая помощь будет принята с благодарностью.

Ответ №1:

Я думаю, вам нужно передать taskId вместо index здесь

 <button onClick={() => removeTask(task.id /*index*/)}>Delete Task</button>
 

поскольку removeTask функция имеет дело taskId не с index


Однако похоже, что у вас нет id поля tasks , даже если вы предполагаете, что оно есть setTasks(prevState => prevState.filter(({ id }) => id !== itemId)); , поэтому, если вы хотите продолжать удалять задачу по индексу, измените removeTask , как показано ниже.

 function removeTask(index) { // remove by index
    setTasks(prevState => {
        const tasks = [...prevState]; // create new array based on current tasks
        tasks.splice(index, 1); // remove task by index
        return tasks; // return altered array
    });
}
 

ДЕМОНСТРАЦИЯ

Ответ №2:

Проблема

Ваш метод удаления использует идентификатор элемента, но вы передаете ему индекс в обработчике кнопки onClick .

Решение

Выберите один или другой из id or index и оставайтесь последовательными.

Использование id

 function removeTask(itemId) {
  setTasks(prevState => prevState.filter(({ id }) => id !== itemId));
}

...

<button onClick={() => removeTask(task.id)}>Delete Task</button>
 

Использование индекса

 function removeTask(itemIndex) {
  setTasks(prevState => prevState.filter((_, index) => index !== itemIndex));
}

...

<button onClick={() => removeTask(index)}>Delete Task</button>
 

Поскольку не похоже, что ваши задачи являются объектами со id свойством, я предлагаю добавить an id к вашим задачам. Это поможет вам позже, когда вы успешно удалите задачу из своего списка, поскольку вы также захотите не использовать индекс массива в качестве ключа реакции, поскольку вы ожидаете изменения своего массива задач.

App.js

 import { v4 as uuidV4 } from 'uuid';

...

function onSubmitTask(e) {
  e.preventDefault();
  setTasks(prevTasks => prevTasks.concat({
    id: uuidV4(), // <-- generate new id
    task
  }));
  setTask("");
}

function removeTask(itemId) {
  setTasks(prevState => prevState.filter(({ id }) => id !== itemId));
}
 

Дочерний элемент

 function Overview({ tasks, removeTask }) {
  return (
    {tasks.map(({ id, task }, index) => { // <-- destructure id amp; task
      return (
        <Fragment key={id}> // <-- react key on outer-most element
          <p>
            #{index   1} {task}
          </p>
          <button onClick={() => removeTask(id)}>Delete Task</button>
        </>
      );
    })}
  );
}