Material-table: Issues when las row in a page is deleted

Created on 2 May 2019  路  17Comments  路  Source: mbrn/material-table

Describe the bug
An error appear after the last row in the second page was deleted.

These are the messages:
"The above error occurred in the component"

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

To Reproduce
Steps to reproduce the behavior:

  1. Create 2 page of element using remote connection
  2. Delete the last element in the second page and the error will appear

version 1.32

bug performance issue

All 17 comments

Hi @orestes22 ,

I could not reproduce this case. Can you create a sandbox please?

Or how do you delete? Show me code.

I have the same remote Get request that you have in your example.

I believe I found the problem. After a Delete API call, i called this.state.tableRef.current.onQueryChange();
in order to update the table, but this call create infinite loop if I delete the last row in a page.
So like isnt another way now to refresh the table after outside API call, my idea to solve the problem is to save the page and pass it again to my call of onQueryChange like something like this this.state.tableRef.current.onQueryChange({page: this.state.page-this.state.count})

where in the state page I will save in which page row im deleting, , and in the state count i will rest 1 if the row to delete is the last one.

Could you share with me your thoughts about my idea? @mbrn

It is a strange case @orestes22 :). Can you create a sandbox for this case? We can play on it together. You can use reqres.in for remote data sample.

Ok, I will create sandbox asap and i will let you know.

Hi, @mbrn I created the sandbox, here it is https://codesandbox.io/s/v8xm9j3287 but you have to write your API URL, because reqres.in dont allow the delete.

I still having the same issues when i delete the last element of a page(if that page is > 0) and after that i called the this.state.tableRef.current.onQueryChange();

In the middle of time Im doing this this.state.tableRef.current.onQueryChange({page:0}); but this is not a good solutions.

Let me know how i can support.
Best Regards

Hi, @mbrn any comment about this.
Regards

Hi @orestes22

Not yet.

Any solutions for this issue?

Any solutions for this issue?

Hi,

Based on your work, @orestes22, I made a workaround to catch almost the worst case.

@mbrn, it seems like the currentPage is not updated. I noticed the current page doesn't reflect the page in the DataManager.

  • I don't really know if a state problem or if I don't read the correct variable.
const needRedirection = refTableContainer.current.dataManager.getRenderState().renderData.length === 1;
const currentPage = refTableContainer.current.dataManager.currentPage;
if (needRedirection) { // why if needRedirection, currentPage seems always zero 
    refTableContainer.current.onQueryChange({ page: currentPage }); 
} else {
     refTableContainer.current.onQueryChange();
}

@IniterWorker You workaround is very good. Thanks for share.

@IniterWorker I found that your workaround dont resolve this situation: if you delete the last row of the last page , the table dont work.

Without more information, @orestes22, maybe your implementation has an issue. I currently use my workaround without a crash on the table.

Create an example using remote connection, the total of element will be 11, the first page show 5 , the second show 5 and the last one will show 1. Try to delete that last row.
Regards

@orestes22 could you improve it? like I said it's a workaround.
B. r

@IniterWorker Yes I could, but right now they are not accepting PR, so , I decided use another table, React-Table, where it isnt depended of the design and I created a table equal to material-table, and also added virtualization and others features.

Have a look it and , let me know if you have any trouble and I will help you.

Best Regards

Update to anyone who encountered this issue, here is my solution:

const [isDelete, setIsDelete] = useState(false)
const getRemoteData = (query) =>
  new Promise((resolve, reject) => {
    const {
      page = 0,
      pageSize = 50,
      orderDirection = "desc",
      orderBy = { id: "expire_datetime" },
      totalCount,
    } = query;
    let realPage = NaN;
    if (totalCount === pageSize * page + 1 && page !== 0 && isDelete) {
      realPage = page;
      setIsDelete(false);
    } else {
      realPage = page + 1;
    }
    const ordering = (orderDirection === "desc" ? "-" : "") + orderBy.id;
    CallGetAPI({ page: realPage, pageSize, ordering }).then((res) => {
      resolve({
        data: res.data.results,
        page: res.data.current - 1,
        totalCount: res.data.count,
      });
    });
  });

return (
  <MaterialTable
    columns={columns}
    data={getRemoteData}
    editable={{
      onRowDelete: (oldData) =>
        new Promise((resolve, reject) => {
          const muteId = oldData.id;
          CallDeleteAPI.then((res) => {
            setIsDelete(true);
            resolve();
          });
        }),
    }}
  />
);

The point is using a flag isDelete and totalCount === pageSize * page + 1
Hope this is helpful.

Was this page helpful?
0 / 5 - 0 ratings