Задать вопрос
@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;
  • Вопрос задан
  • 114 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Самый простой способ - перенести вызов setIsDeleted из finally в catch.

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

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

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

Похожие вопросы
ITK academy Нижний Новгород
от 80 000 до 120 000 ₽
ITK academy Воронеж
от 50 000 до 90 000 ₽