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:
- First request is made with
pageParam = 0
, the backend's response will containoffset: 0
. getNextPageParam
uses this value to calculate theactualPage
:offset / limit
which equals to 0 / 10, soactualPage
will have a value of 0.- Since
actualPage < totalPages
, then the next page param will beactualPage + 1
which equals to 0 + 1. Next page will now have a value of 1. - This value is passed to your
queryFn
for the next request, so now theoffset
will be 10. - The backend's response offset will now be 10.
- And so on...
Let me know if that helps.
Related Topics
How to Access the Content of the "Embed" Tag in HTML
Modify the Value of Each Textfield Based on Original Value Using Jquery
Cross Browser Rgba Transparent Background While Keeping Content (Text & Images) Non-Transparent
Blend Mode:Multiply in Internet Explorer
Javascript: Hiding and Showing Div Tag with a Toggle Button
Css/JavaScript Use Div to Grey Out Section of Page
Is There a Performance Difference Between the Sx Prop and the Makestyles Function in Material Ui
How to Add Custom CSS/Js to Just One Page in Wordpress
Show One Bootstrap Carousel Item in Mobile
How to Build Simple Sticky Navigation with Jquery
Jquery Event Not Triggering for Dom Elements Created After Page Load
How to Style a Title? (And with CSS or Js)
How to Make a Div Always Float on the Screen in Top Right Corner
Google Maps Marker - Set Background Color
How to Disable a Specific Li Element Inside a Ul