Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagination example with page numbers? #44

Closed
roxeteer opened this issue Oct 30, 2019 · 9 comments
Closed

Pagination example with page numbers? #44

roxeteer opened this issue Oct 30, 2019 · 9 comments

Comments

@roxeteer
Copy link

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.

@roxeteer
Copy link
Author

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.

@shuding
Copy link
Member

shuding commented Oct 30, 2019

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.

@shuding
Copy link
Member

shuding commented Nov 6, 2019

👋 this feature has landed in swr@0.1.7, here's an example:

https://codesandbox.io/s/swr-playground-946db

Closing this issue now.

@shuding shuding closed this as completed Nov 6, 2019
@roxeteer
Copy link
Author

roxeteer commented Nov 6, 2019

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.

@grazianodev
Copy link

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!

@shuding
Copy link
Member

shuding commented Nov 7, 2019

Hi @grazianodev !

I noticed the exact same bug as you had, and already created a PR to fix it (there's also an example): #95

We will review and ship it today in the next version, will let you know!

@shuding
Copy link
Member

shuding commented Nov 9, 2019

We just shipped the improvements in swr@0.1.9, 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

@grazianodev
Copy link

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).

@shuding
Copy link
Member

shuding commented Nov 10, 2019

@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 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants