React-table: double fetching when manual

Created on 5 May 2019  路  8Comments  路  Source: tannerlinsley/react-table

Using v6

Describe the bug
onFetchData calls twice when using manual data and change page,
It looks like that one call is after click on button and another after change page state.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/s/z37o0vqpmx
  2. Click on Next
  3. See the concole
  4. changePage(pageIndex: 11)
    index.js:26 fetchData(page: 11)
    index.js:26 render(page: 11, pageCount: 5553)
    index.js:26 fetchData(page: 11)
    index.js:26 render(page: 11, pageCount: 5553)

Expected behavior
I expect that one click on Next call one fetchData

Codesandbox!
https://codesandbox.io/s/z37o0vqpmx

Most helpful comment

@tannerlinsley thanks for this excellent work. Unfortunately, we do not have enough resources to test the v7 for now. I wanted to share the following workaround until we got time to investigate the v7.

We simply use a debounce function that will trigger the trailing call (we use the lodash one):

import { debounce } from 'lodash';
// ...
onFetchData = async ({ page, pageSize, sorted, filtered }, instance) => {
  // fetch code here
};
debouncedFetchData = debounce(this.onFetchData, 200);

render() {
  // ...
  page={page}
  onPageChange={this.onPageChange}
  sorted={sorted}
  onSortedChange={this.onSortedChange}
  onFetchData={this.debouncedFetchData}
  // ...
}

By doing so, we do not have duplicate call nor error at the mounting phase (we use query params to define the initial state).

All 8 comments

Hi!

You change "page" in changePage function.
After change "page" TableReact call onFetchData (see more https://github.com/tannerlinsley/react-table/blob/v6/src/lifecycle.js line 118)

@ElfenLiedGH I'v understood it. But how could I change page another way?

After many hours of debugging I think that you couldn't use

manual={true}
onFetchData={...}

together with controlled-component-style props.

sorted={sorted}
page={page}
filtered={filtered}
onSortedChange={this.handleSortedChange}
onPageChange={this.handlePageChange}
onFilteredChange={this.handleFilteredChange}

Sometimes it looks like that everything is working, but you will be struggling with double data fetching and small issues, for example when you change the sorting, current page number failed to reset to 0 (onPageChange callback won't be called!), which introduces conflicts between internal state and props of ReactTable component, which also leads to calling onFetchData twice.

Could someone confirm this?

Related issue: https://github.com/tannerlinsley/react-table/issues/696

I think I've the same issue. Initial load is OK. First click on sort or first filter thing -> triggers 2 API calls. And results of filter operation can be received in wrong order.

I also reviewed the related ticket: but I bind filtered and page and sorted to the URL query parameters: to achieve good working history/back functionality.

The double call:

  • it's first a call without the new filter
  • then the correct call

When I remove the filtered={filtered} -> the double API call isn't there: but then you can's see the current filtered value when a page is (re)loaded (which should be loaded from URL query parameters).

Hi there! It looks as though you've submitted an issue or feature request for v6 of React Table, which I am no longer maintaining or supporting. I invite you to try the latest alpha release of v7 and help me push towards a v7 release soon. Thankyou!

If you still wish to discuss v6, please use https://spectrum.chat/react-table.

I found some sort of workaround as only the filters are affected. So I bind 'page', 'pagesize', and 'sorted' to the url and when I navigate to the detail view I push the current 'filtered' setting to the history, so that the browser back button works ok.

I will try the v7 next week. I am a bit reluctant in running alpha releases on prod, but I will certainly invest some time to get it working in a hobby project first, and document the process. (count me in if v7 internal api is stable enough for some docs of tables with paginate, filter and sort in the backend)

@tannerlinsley thanks for this excellent work. Unfortunately, we do not have enough resources to test the v7 for now. I wanted to share the following workaround until we got time to investigate the v7.

We simply use a debounce function that will trigger the trailing call (we use the lodash one):

import { debounce } from 'lodash';
// ...
onFetchData = async ({ page, pageSize, sorted, filtered }, instance) => {
  // fetch code here
};
debouncedFetchData = debounce(this.onFetchData, 200);

render() {
  // ...
  page={page}
  onPageChange={this.onPageChange}
  sorted={sorted}
  onSortedChange={this.onSortedChange}
  onFetchData={this.debouncedFetchData}
  // ...
}

By doing so, we do not have duplicate call nor error at the mounting phase (we use query params to define the initial state).

I'm having the same problem.

Since the whole table is locked while loading, we know that no other valid requests will be made while loading - any further requests should be this bug. So I simply ignore any requests made while already loading by returning early from onFetchData instead of actually fetching anything.

edit:
Turns out that the user can still type into the filter field while loading. My new solution is a fair bit more complicated:

  • If loading and no parameter changed from the last onFetchData call, just abort by returning instead starting a request.
  • If loading and a parameter changed since the last onFetchData call, cancel any running requests (in my case via axios' CancelToken) and start a new request.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Abdul-Hameed001 picture Abdul-Hameed001  路  3Comments

ocalde picture ocalde  路  3Comments

mlajszczak picture mlajszczak  路  3Comments

pasichnyk picture pasichnyk  路  3Comments

bdkersey picture bdkersey  路  3Comments