@HalvinBRO

Как исправить ошибку при удалении элемента списка?

Доброго времени суток!
Столкнулся с ошибкой, появляющейся в консоли после удаления элемента списка из массива:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in Note (at Table.js:14)


Как это исправить? Понимаю, что это как-то связано с преждевременным размонтированием компонента перед завершением api запроса.

Вот код задействованных компонентов:
1. App.js, где рендерится список:
import React, { useState } from "react";
import { api } from "../utils/api";
import Table from "./Table";

function App() {
  const [notes, setNotes] = useState([]);
  const [isLoad, setIsLoad] = useState(false);

  // Рендер записей с сервера
  React.useEffect(() => {
    api
      .getRecords()
      .then((recordsData) => {
        setNotes(recordsData);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  // Добавление записи в таблицу
  function addNewNote(newData) {
    setIsLoad(true);

    const newRecord = {
      data: newData,
    };

    api
      .putRecords(newRecord)
      .then((res) => {
        setNotes([...notes, res]);
      })
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        setIsLoad(false);
      });
  }

  return (
    <Table
      notes={notes}
      setNotes={setNotes}
      onAddNewNote={addNewNote}
      isLoad={isLoad}
    />
  );
}

export default App;


2. Table.js, в который я прокидываю полученный массив для его отображения на странице:
import React from "react";
import Note from "./Note";
import NewNote from "./NewNote";

function Table({ notes, onAddNewNote, isLoad, setNotes }) {
  return (
    <div className="table">
      <h1 className="table__title">Таблица CRUD</h1>
      <div className="table__add-area">
        <NewNote handleNewNote={onAddNewNote} isLoad={isLoad} />
      </div>
      <div className="table__list">
        {notes.map((note, i) => (
          <Note
            key={note._id}
            dataNote={note}
            notes={notes}
            setNotes={setNotes}
          />
        ))}
      </div>
    </div>
  );
}

export default Table;


3. Note.js - компонент, необходимый для отображения самого элемента массива:
import React, { useState } from "react";
import { api } from "../utils/api";
import NoteTextArea from "./NoteTextArea";

function Note({ dataNote, notes, setNotes }) {
  const [isEdit, setIsEdit] = useState(false);
  const [isLoaded, setIsLoaded] = useState(false);
  const [isDeleted, setIsDeleted] = useState(false);
  const [note, setNote] = useState({
    name: dataNote.data.name,
    age: dataNote.data.age,
    email: dataNote.data.email,
    phone: dataNote.data.phone,
  });

  function onCardClickEdit() {
    setIsEdit(true);
  }

  function handleChange(e) {
    const { name, value } = e.target;
    setNote((note) => ({
      ...note,
      [name]: value,
    }));
  }

  // Редактирование записи
  function editNote() {
    setIsLoaded(true);

    api
      .editRecord(dataNote._id, note)
      .then(() => {
        setIsEdit(false);
      })
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        setIsLoaded(false);
      });
  }

  // Удаление записи из таблицы
  function removeNote() {
    setIsDeleted(true);

    api
      .deleteRecord(dataNote._id)
      .then(() => {
        setNotes(notes.filter((n) => n._id !== dataNote._id));
      })
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        setIsDeleted(false);
      });
  }

  return (
    <NoteTextArea
      dataNote={dataNote}
      isEdit={isEdit}
      isLoaded={isLoaded}
      note={note}
      onCardClickEdit={onCardClickEdit}
      handleChange={handleChange}
      deleteNote={removeNote}
      editNote={editNote}
      isDeleted={isDeleted}
    />
  );
}

export default Note;
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Самый простой способ - перенести вызов setIsDeleted из finally в catch.

Понимаю, что это как-то связано с преждевременным размонтированием компонента перед завершением api запроса.

Не связано. Запрос успешно завершается, удаляется элемент данных, соответствующий ему экземпляр компонента тоже долой - и уже после этого вы пытаетесь обновить состояние экземпляра компонента. А зачем? Не всё ли равно, как он будет выглядеть, если его уже нет?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
25 апр. 2024, в 15:31
70000 руб./за проект
25 апр. 2024, в 15:26
15000 руб./за проект
25 апр. 2024, в 15:13
3000 руб./за проект