Infinite Scrolling with React Js

React Infinite scroll, how to not re-render previous items

You should use React.memo for CountryCard component. codesandbox

If you want to optimize a component(CountryCard) and memoize the result, you wrap it(CountryCard) with React.memo.

Please take a look at React.memo documentation.

How can I implement infinite scrolling on a table using react-virualised?

A working example of infinite scroll on a table element. Also a working a repl.

import React, {useState, useEffect} from 'react';
import './App.css';

function App() {
let items = [];
for (let i = 0; i < 100; i++) {
items.push({
key: 'foo' + i,
value: 'bar' + i,
});
}

let dataTable = React.createRef();

const [list, setList] = useState({
itemsDisplayed: 20,
data: items.slice(0, 20),
});

let onScroll = () => {
let tableEl = dataTable.current;
if (tableEl.scrollTop === (tableEl.scrollHeight - tableEl.offsetHeight)) {
if (list.itemsDisplayed + 10 <= items.length) {
setList({
itemsDisplayed: list.itemsDisplayed + 10,
data: items.slice(0, list.itemsDisplayed + 10),
});
}
}
};

return (
<div className="App">
<table id="data-table" ref={dataTable} onScroll={onScroll}>
<tbody>
{list.data.map((item) => {
return (
<tr key={item.key}>
{item.value}
</tr>
);
})}
</tbody>
</table>
</div>
);
}

export default App;

Also to mention, the problem of scrolling firing only once solved by this question. The point is to use React's built-in onScroll event.

Implement infinite query with traditional backend pagination

Since your paginated queries depend on offset and limit you can do something like:

const { data, hasNextPage } = useInfiniteQuery(['queryKey'], ({ pageParam = 0 }) => queryFn(pageParam), {
getNextPageParam: (lastPage) => {
const totalPages = Math.floor(lastPage.totalResults / lastPage.limit)
const actualPage = lastPage.offset / lastPage.limit
return actualPage < totalPages ? actualPage + 1 : undefined // By returning undefined if there are no more pages, hasNextPage boolean will be set to false
}
})

const queryFn = async (page) => {
const limit = 10
const offset = page * limit
const res = await fetch(`https://some-endpoint/search?limit=${limit}&offset=${offset}`)

...
}

Explanation:

The first request to the backend will be made with pageParam = 0 by default, therefore, in the queryFn the offset will be calculated to 0 to retrieve the first items from the backend. From what you explain in your post, the backend will also return this offset on each response, which will be used to calculate the actualPage in getNextPageParam.

It goes like:

  1. First request is made with pageParam = 0, the backend's response will contain offset: 0.
  2. getNextPageParam uses this value to calculate the actualPage: offset / limit which equals to 0 / 10, so actualPage will have a value of 0.
  3. Since actualPage < totalPages, then the next page param will be actualPage + 1 which equals to 0 + 1. Next page will now have a value of 1.
  4. This value is passed to your queryFn for the next request, so now the offset will be 10.
  5. The backend's response offset will now be 10.
  6. And so on...

Let me know if that helps.



Related Topics



Leave a reply



Submit