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

infinite: do not revalidate every page on mutate(undefined) #1590

Open
hazae41 opened this issue Oct 25, 2021 · 11 comments
Open

infinite: do not revalidate every page on mutate(undefined) #1590

hazae41 opened this issue Oct 25, 2021 · 11 comments
Labels
area: infinite area: mutation discussion Discussion around current or proposed behavior

Comments

@hazae41
Copy link

hazae41 commented Oct 25, 2021

Bug report

Description / Observed Behavior

When I use .mutate(), all pages are revalidated even tough nothing changed in the first page, and the keys didn't change

This behaviour happens regardless of revalidateIfStale, and regardless of the new revalidateFirstPage

Expected Behavior

Do not revalidate if the first page is the same and keys are the same

Repro Steps / Code Example

const key = useCallback((page: number, previous: Data | null) => {
  // First page
  if (page === 0 || !previous)
    return h(`topics`) // h is just a query builder
  // No next page
  if (!previous.after)
    return null
  // Next page
  const [after] = previous.after
  return h(`topics`, { after })
}, [])

const res = useSWRInfinite<Data>(key, fetcher, {})

const refresh = useCallback(() => {
  res.mutate()
}, [res])

return <button onClick={refresh}>
  refresh
</button>

Additional Context

happening on both swr@1.0.1 and swr@1.1.0-beta.6

@hazae41 hazae41 changed the title infinite: do not revalidate every page when using mutate on cursor-based pagination infinite: do not revalidate every page on cursor-based pagination Oct 27, 2021
@hazae41
Copy link
Author

hazae41 commented Oct 27, 2021

This also happens on automatic revalidation

@hazae41
Copy link
Author

hazae41 commented Oct 27, 2021

Ok, this comes to the fact that mutate() becomes mutate(undefined)

Fix is:

const refresh = useCallback(() => {
  res.mutate(d => d, true)
}, [res.mutate])

@hazae41 hazae41 closed this as completed Oct 27, 2021
@hazae41
Copy link
Author

hazae41 commented Nov 5, 2021

Still happens on beta 8, all pages are revalidated when doing mutate(undefined)

const refresh = useCallback(() => {
  res.mutate(d => d, true)
}, [res.mutate])

@hazae41 hazae41 reopened this Nov 5, 2021
@hazae41 hazae41 changed the title infinite: do not revalidate every page on cursor-based pagination infinite: do not revalidate every page on mutate(undefined) Nov 5, 2021
@shuding
Copy link
Member

shuding commented Dec 1, 2021

Very weird, let me try to reproduce this.

@shuding shuding added the bug Something isn't working label Dec 1, 2021
@shuding
Copy link
Member

shuding commented Dec 23, 2021

If you call res.mutate(), everything will be revalidated. That's currently the expected behavior:

swr/infinite/index.ts

Lines 190 to 191 in e167752

// Calling `mutate()`, we revalidate all pages
cache.set(contextCacheKey, [true])

We need to improve the local mutation API for pages a bit.

@shuding shuding added discussion Discussion around current or proposed behavior area: pagination Pagination related issues and removed bug Something isn't working labels Dec 23, 2021
@iDarkLightning
Copy link

Hi!

Have there been any updates regarding this issue? I'd like to be able to mutate & revalidate a specified page, and not all the loaded pages when calling mutate(). Is this possible in any way with the current implementation?

@koba04 koba04 added area: infinite and removed area: pagination Pagination related issues labels Mar 8, 2023
@misa-minic
Copy link

Hi!
Any updates regarding this issue?

@hazae41
Copy link
Author

hazae41 commented Jun 20, 2023

If you find this annoying, you can use my library

https://github.com/hazae41/xswr

You can revalidate any single page without revalidating everything

@misa-minic
Copy link

misa-minic commented Jun 22, 2023

I have to use SWR only, but I found some work around. Thanks!

@khanhld1910
Copy link

hi @misa-minic could you share your solution? I thought about storing all items into a useState and then modifying a specific item after it's updated but I feel there should be a better solution

@misa-minic
Copy link

Hi @khanhld1910
Sorry for the late reply, I hope you found the solution by now.

If not, take a look at:
https://swr.vercel.app/docs/mutation.en-US#mutate-multiple-items

You should be able with mutate to update only a certain KEY which represents each api call/url for getting a next "page" of items.
In my case, I find the index of the item I updated e.g. index 15, then I could say, refetch only 10 items, from index 10 to index 20. This way I am not updating all the fetched items, but only 10 among which is my updated item.

Let me know if you need some info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: infinite area: mutation discussion Discussion around current or proposed behavior
Projects
None yet
Development

No branches or pull requests

6 participants