Проблема с удалением элемента из массива

Пишу ToDo. Столкнулся с проблемой: при удалении задачи из массива вылезает ошибка Cannot set property 'Вставьте слово' of undefined. Ошибка вылезает только если создано 2 и более задач. Проблема в функции deleteTask(). Пытался удалять с помощью delete - та же история. Что нужно сделать, чтобы удалялся один элемент массива и не вылезала эта ошибка?

Вот код:

(function() {
    // ToDo

    const tasks = [];

    (function() {
        // UI
        const addTask = document.getElementById('addNewTask'),
            addTaskBut = addTask.elements.addTaskBut,
            taskContent = addTask.elements.taskText;

        // Events
        window.onload = () => {
            loadTasks();
        };

        addTaskBut.addEventListener('click', createTask);

        // Functions
        function createTask(e) {
            e.stopPropagation();
            e.preventDefault();

            if (!taskContent.value) {
                alert('Нельзя создать пустую задачу');
                return;
            }

            const task = {
                id: Math.random(),
                content: taskContent.value
            };

            tasks.push(task);

            loadTasks();

            console.log(tasks);
        }

        function loadTasks() {
            const fragment = document.createDocumentFragment(),
                fragmentAppend = document.querySelector('.tasks');

            fragmentAppend.innerHTML = '';

            tasks.forEach(task => {
                let item = document.createElement('div'),
                    content = document.createElement('div'),
                    deleteBtn = document.createElement('button');

                item.classList.add('task');
                content.classList.add('content');
                deleteBtn.classList.add('deleteBtn');

                item.setAttribute('data-id', task.id)

                content.textContent = task.content;
                deleteBtn.textContent = 'Удалить';

                item.appendChild(content);
                item.appendChild(deleteBtn);
                fragment.appendChild(item);
            });

            fragmentAppend.appendChild(fragment);

            fragmentAppend.addEventListener('click', deleteTask, { capture: true })
        }

        function deleteTask(e) {
            e.stopPropagation();
            if (e.target.classList != 'deleteBtn') {
                return;
            } else {
                console.log(2);
                const parent = e.target.closest('[data-id').dataset.id;
                const deleteChange = tasks.reduce((acc, task) => {
                    if (acc[task.id] = parent) {
                        tasks.splice(0, task);
                        loadTasks();
                        return;
                    }
                }, {});
            }
        }
    }(tasks));
}());
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

.container {
    width: 1200px;
    margin: 0 auto;
}

section.todo {
    margin-top: 100px;
}

section.todo .container {
    text-align: center;
    width: 500px;
}

section.todo .container form {
    display: flex;
    justify-content: space-between;
    margin: 0 auto
}

section.todo .container form input {
    padding: 7px 14px;
}

section.todo .container form [name="addTaskBut"] {
    background-color: #fff;
    border: 1px solid #000;
    cursor: pointer;
}

section.todo .container form [name="taskText"] {
    width: 440px;
}

section.todo .container .tasks .task {
    border: 1px solid #000;
    padding: 10px 15px;
    margin-top: 10px;
    position: relative;
}

section.todo .container .tasks .task .content {
    font-family: sans-serif;
    width: 300px;
    margin: 0 auto;
    word-wrap: break-word;
}

section.todo .container .tasks .task .deleteBtn {
    background-color: #fff;
    border: none;
    border-right: 1px solid #000;
    border-bottom: 1px solid #000;
    padding: 3px 7px;
    position: absolute;
    top: 0;
    left: 0;
    cursor: pointer;
    outline: none;
}
<!DOCTYPE html>
<html lang="ru">

<head>
    <meta charset="utf-8">
    <title>ToDo</title>

    <link rel="stylesheet" href="css/main.css">
</head>

<body>
    <header>
        <div class="container">
            <div class="logo">ToDo</div>
        </div>
    </header>

    <section class="todo">
        <div class="container">
            <form name="addTask" id="addNewTask">
                <input type="submit" name="addTaskBut" value="add">
                <input type="text" name="taskText">
            </form>
            <div class="tasks"></div>
        </div>
    </section>
    <script src="js/app.js"></script>
</body>

</html>

(лучше разворачивать на всю страницу).


Ответы (1 шт):

Автор решения: Grundy

В коде смешалось сразу несколько подходов, поэтому и не работает.

const deleteChange = tasks.reduce((acc, task) => {
    if (acc[task.id] = parent) {
        tasks.splice(0, task);
        loadTasks();
        return;
    }
}, {});
  1. reduce НЕЛЬЗЯ остановить.
  2. в данном случае из функции коллбэка ничего не возвращается. В этом случае на второй итерации acc всегда undefined, поэтому и возникает ошибка при попытке обращения к его свойству.
  3. менять массив по которому происходит итерация - не самая лучшая идея, особенно, когда в качестве числа идете попытка передать объект.

Вместо этого кода можно было использовать простой filter

tasks = tasks.filter(task => task.id != parent);

(function() {
  // ToDo

  let tasks = [];

  (function() {
    // UI
    const addTask = document.getElementById('addNewTask'),
      addTaskBut = addTask.elements.addTaskBut,
      taskContent = addTask.elements.taskText;

    // Events
    window.onload = () => {
      loadTasks();
    };

    addTaskBut.addEventListener('click', createTask);

    // Functions
    function createTask(e) {
      e.stopPropagation();
      e.preventDefault();

      if (!taskContent.value) {
        alert('Нельзя создать пустую задачу');
        return;
      }

      const task = {
        id: Math.random(),
        content: taskContent.value
      };

      tasks.push(task);

      loadTasks();

      console.log(tasks);
    }

    function loadTasks() {
      const fragmentAppend = document.querySelector('.tasks');

      fragmentAppend.innerHTML = '';

      const fragment = tasks.reduce((fragment, task) => {
        let item = document.createElement('div'),
          content = document.createElement('div'),
          deleteBtn = document.createElement('button');

        item.classList.add('task');
        content.classList.add('content');
        deleteBtn.classList.add('deleteBtn');

        item.setAttribute('data-id', task.id)

        content.textContent = task.content;
        deleteBtn.textContent = 'Удалить';

        item.appendChild(content);
        item.appendChild(deleteBtn);
        fragment.appendChild(item);
        return fragment;
      }, document.createDocumentFragment());

      fragmentAppend.appendChild(fragment);

      fragmentAppend.addEventListener('click', deleteTask, {
        capture: true
      })
    }

    function deleteTask(e) {
      e.stopPropagation();
      if (e.target.classList != 'deleteBtn') {
        return;
      } else {
        const parent = e.target.closest('[data-id]').dataset.id;
        tasks = tasks.filter(task => task.id != parent);
        loadTasks();
      }
    }
  }(tasks));
}());
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.container {
  width: 1200px;
  margin: 0 auto;
}

section.todo {
  margin-top: 100px;
}

section.todo .container {
  text-align: center;
  width: 500px;
}

section.todo .container form {
  display: flex;
  justify-content: space-between;
  margin: 0 auto
}

section.todo .container form input {
  padding: 7px 14px;
}

section.todo .container form [name="addTaskBut"] {
  background-color: #fff;
  border: 1px solid #000;
  cursor: pointer;
}

section.todo .container form [name="taskText"] {
  width: 440px;
}

section.todo .container .tasks .task {
  border: 1px solid #000;
  padding: 10px 15px;
  margin-top: 10px;
  position: relative;
}

section.todo .container .tasks .task .content {
  font-family: sans-serif;
  width: 300px;
  margin: 0 auto;
  word-wrap: break-word;
}

section.todo .container .tasks .task .deleteBtn {
  background-color: #fff;
  border: none;
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 3px 7px;
  position: absolute;
  top: 0;
  left: 0;
  cursor: pointer;
  outline: none;
}
<!DOCTYPE html>
<html lang="ru">

<head>
  <meta charset="utf-8">
  <title>ToDo</title>

  <link rel="stylesheet" href="css/main.css">
</head>

<body>
  <header>
    <div class="container">
      <div class="logo">ToDo</div>
    </div>
  </header>

  <section class="todo">
    <div class="container">
      <form name="addTask" id="addNewTask">
        <input type="submit" name="addTaskBut" value="add">
        <input type="text" name="taskText">
      </form>
      <div class="tasks"></div>
    </div>
  </section>
  <script src="js/app.js"></script>
</body>

</html>

→ Ссылка