Our backend uses page number for pagination (first page is 0, second page is 1, and so on). What would be the correct way to implement that with useSWRPages()?
My current implementation works so that I'm using this as my swrDataToOffset function:
data => !data || !pages || pages.length === 0 ? 0 : pages.length - 1
Also, I'm not sure if it's a problem with my implementation, but as I'm trying useSWRPages() out in our Next.js application, I'm getting this exception when the application is hot reloaded (HMR) and there were several pages fetched before the reload:
Warning: Encountered two children with the same key, `page-2`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
I think got rid of the exceptions by changing the swrDataToOffset function to return pages.length instead of pages.length - 1. But now after loading more data after SWR displays the cached data, I get the last page again. I'll try to create a simplified version of our component for an example.
One more thing: is there a way for a page to tell that there will be no more data available (so I could hide the element triggering a fetch)? Now I get more and more pages even if they are empty. Returning null from the page component doesn't seem to have an effect.
Hi @roxeteer !
I think we'll need a second parameter like pageCount or pageSWRs, for the function swrDataToOffset, because that function shouldn't depend on any state outside for performance considerations. So ideally you'll have:
(data, pageSWRs) => pageSWRs.length
as your swrDataToOffset function.
Regarding
One more thing: is there a way for a page to tell that there will be no more data available
There's a isReachingEnd value also returned from useSWRPages. If your swrDataToOffset returns null, it will be considered as the last page:
const { isReachingEnd } = useSWRPages(
...,
...,
(data, pageSWRs) => {
if (!data.hasNextPage) return null
return pageSWRs.length
}
)
You can conditionally return null based on the data returned from the API.
👋 this feature has landed in [email protected], here's an example:
https://codesandbox.io/s/swr-playground-946db
Closing this issue now.
Great! Never had the chance to return to my SWR experiments. I'll see what I can achieve with v0.1.7 when I have my other project tasks done.
Hi,
thank you for your efforts, however it seems like something's not working well, even in the example you posted on CodeSandbox. If I click the 'load next page' button a few times you get the following, which is correct:
content of page 0
content of page 1
content of page 2
content of page 3
content of page 4
However if I switch to another tab or window and return to CodeSandbox, this is what I see:
content of page 0
content of page 5
content of page 5
content of page 5
content of page 5
I've implemented the example working with a real API and I see the error again: I get the data just fine initially, but if I switch tab or window and go back, suddenly the original data is replaced with repeated content from the same page. Basically, it behaves as described above. Restoring the scrolling position doesn't seem to work either: if from page A (where I fetch my data) I scroll 400px, then I visit page B and scroll e.g. 200px, and then go back to page A via the back button, I would expect to be at 400px from the top but I'm actually at 200px (in other words, it applies to page A the last scrolling position of page B).
I really like the potential of this library so it would be great if I could get this working! Please note that I'm not a very experienced developer so I might be doing something wrong or missing something. Thank you for any help!
Hi @grazianodev !
I noticed the exact same bug as you had, and already created a PR to fix it (there's also an example): https://github.com/zeit/swr/pull/95
We will review and ship it today in the next version, will let you know!
We just shipped the improvements in [email protected], it has a much simpler interface now. You can take a look at an example here:
https://github.com/zeit/swr/blob/master/examples/pagination/pages/page-index.js
Thank you for your work!
I have made some tests with the new version and the bug I described earlier is definitely gone. However I still have some issues with restoring the scrolling position.
I am currently testing with a frontend that makes an API request to fetch a list of posts from a backend that uses a Wordpress installation. When I visit the page of a single post from the homepage (where the list of posts is), then hit the back button to return to the homepage, the SWR library requests the lists of posts again (to revalidate the data, I imagine), which takes some time; but the scrolling position is restored immediately, so what happens is that the restoration is done when I'm still on the single page, causing a jump in this page before returning to the homepage, which is a bit nasty. Another issue I've noticed with scrolling is that if I've scrolled 3000px on the homepage, and visit a single post page that is 2000px tall, then hit the back button, the restoration of the scrolling position is not precise; on the contrary, if the single page is taller than what I've initially scrolled it is always correct. (Just pointing it out, I'm not even sure if this being super precise is within the scope of SWR).
I do have one more question. In this use case (just retrieving a set of posts) I don't really need to revalidate the data, so is there a way to just fetch the cached posts without revalidating when I return to the homepage? (I guess this would conveniently also solve the first scrolling issue since, with no revalidation requests, hitting the back button would immediately bring me back to the homepage).
@grazianodev is this a client side transition (e.g.: history.pop)?
then hit the back button to return to the homepage
If not, SWR cannot reuse the cache (since it's in the memory) and restore the list unfortunately.
I don't really need to revalidate the data
Yeah we plan to provide that option 👍
Most helpful comment
I think got rid of the exceptions by changing the
swrDataToOffsetfunction to returnpages.lengthinstead ofpages.length - 1. But now after loading more data after SWR displays the cached data, I get the last page again. I'll try to create a simplified version of our component for an example.One more thing: is there a way for a page to tell that there will be no more data available (so I could hide the element triggering a fetch)? Now I get more and more pages even if they are empty. Returning
nullfrom the page component doesn't seem to have an effect.