H
H
HalvinBRO2021-07-09 01:28:25
React
HalvinBRO, 2021-07-09 01:28:25

How to fix error when deleting list item?

Good day!
I encountered an error in the console after removing a list item from an array:
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)


How to fix this? I understand that this has something to do with premature unmounting of the component before completing the api request.

Here is the code of the components involved:
1. App.js where the list is rendered:

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, into which I pass the resulting array to display it on the page:
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 - the component required to display the array element itself:
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;

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2021-07-09
@HalvinBRO

The easiest way is to move the setIsDeleted call from finally to catch.

I understand that this has something to do with premature unmounting of the component before completing the api request.

Not connected. The request completes successfully, the data element is deleted, the component instance corresponding to it is also down - and after that you are trying to update the state of the component instance. What for? Does it matter how it will look if it is already gone?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question