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

Clear page cache on resetPages and page key changes #269

Closed
wants to merge 1 commit into from

Conversation

innocentiv
Copy link
Contributor

Adding a Reset for pages

based on the work of patrickus and gabrielperales@8ba8379

This is a copy of the Pull Request from patrickus
with the following changes:

  • reset pageCacheMap to ensure offset is computed after a reset is performed
  • restore types
  • restore JSX for page components (we need better eslint config to avoid warnings, pr coming)
  • remove unneeded useMemo call on pageCountKey and pageOffsetKey (strings are primitive values)

resolving: #189

Sorry for the duplicated PR, I needed those fixes for today so I created a fix on my repo. Disregard this PR if patrickus want to improve the work done on his PR.

thanks to https://github.com/patrickus and https://github.com/gabrielperales

@@ -205,7 +219,7 @@ export function useSWRPages<OffsetType = any, Data = any, Error = any>(
p.push(pageCache[i].component)
}
return p
}, [_pageFn, pageCount, pageSWRs, pageOffsets, pageKey])
}, [_pageFn, pageCount, pageSWRs, pageOffsets, pageKey, pageOffsetKey])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@innocentiv pageOffsetKey will always change with pageKey... so it is not needed to put it here as a dependency, is it needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not actually needed, but I think the recommended approach is to add all the values used inside the effect as a dependency to avoid stale closure pitfalls. There is none in this case, thanks to the link between pageKey and pageOffsetKey , but I think it helps with code clarity and in future refactor. The link between these two values is elsewhere in the codebase, and the is no problem in adding a dependency. In general, there are lots of missing dependencies in swr. The issue was also discussed here: #263 . We should try to decide the best way to manage dependencies in hooks.

More info here: facebook/react#14920 (comment)
dan abramov blog: https://overreacted.io/a-complete-guide-to-useeffect/#dont-lie-to-react-about-dependencies
react docs: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see... Thanks for clarifying it. Let's see if any of the reviewers decides to check the code soon. I've been waiting a lot this feature to be merged!

@innocentiv
Copy link
Contributor Author

Hi, reviewers. It has been a month, could I ask you why nobody is reviewing this MR?
Right now the pagination is broken if you are changing the key to get a new page list.
If there is any issue, or you think that this is not a good solution, just tell us what to do.

@muyiwaoyeniyi
Copy link

@innocentiv Thanks for this fix. I will use your branch until the fix is official.

Thanks.

@muyiwaoyeniyi
Copy link

@innocentiv Maybe consider clearing out the cache for each page swr in resetPages..

@sanderfish
Copy link

sanderfish commented Mar 30, 2020

Would love to see this merged.

Edit: @quietshu just realised where you are. Hope you're ok, wishing you the best!

@muyiwaoyeniyi
Copy link

@innocentiv I'm having issues installing/building the project. After installing the repo with npm, I'm unable to reference 'swr' and when I try building it myself, I run into (I guess typescript type) errors. I will appreciate any help with this.

Thanks.

@innocentiv
Copy link
Contributor Author

@muyiwaoyeniyi This branch does no contain the build artifact for swr. I have created a branch https://github.com/innocentiv/swr/tree/reset-pages-build with a build for use in my projects. This build was made some time ago, on an older release and I cannot guarantee there would be no regression. You could try it with:

npm install github:innocentiv/swr#reset-pages-build

@muyiwaoyeniyi
Copy link

@innocentiv Got it. Thanks.

justsee added a commit to otsu-app/swr that referenced this pull request Apr 15, 2020
@gabrielperales
Copy link

c'mon!

@Jack-Works
Copy link

Using this branch, the stale offset bug is fixed, thanks!
But there are still strange bugs, I try to debug the hooks state

image

The final array is offset array.

As you can see, when switch from old page key suj to new page key suji, there is a moment (Bad state 1 in the picture) that old offsets is mixed with new pageKey.

And in the bad state 2, for unknown reason, the page count increased (but I only have 1 page of data), and useSWRPages start to return duplicated data.

image

Green box: Original data
Yellow box: Duplicated data (I believe it's coming from offset[1])
Red box: Duplicated data (I believe it's coming from offset[2])

This bug is not stable, depends on how I type the search query so I believe it's some kind of race condition.

@Jack-Works
Copy link

(I'm using useSWRPages for infinite loading so the loadMore function is called automatically, therefore it's easier to trap the race condition bug)

@innocentiv
Copy link
Contributor Author

@Jack-Works and @muyiwaoyeniyi thank you for testing this PR. I think more unit tests are needed. I will be working on this as soon as possible.

@muyiwaoyeniyi
Copy link

@innocentiv My pleasure. @Jack-Works I've seen that issue and I also have an infinite loading implementation with react-window so it all works out.

@Jack-Works
Copy link

@muyiwaoyeniyi oh how do you use it with react-window? Can you share an example? Maybe I did something wrong therefore having bugs in it.

@muyiwaoyeniyi
Copy link

@Jack-Works Certainly. I can put chunks of my code on codesandbox. That would be the quickest option for me. It would take some time to cut it down to highlight the key parts. As a side note, I normalize all responses from my api so it inherently removes duplicates.

Let me know if that works and I'll put it up.

Thanks.
Taiwo

@muyiwaoyeniyi
Copy link

@Jack-Works Here's my code.

https://codesandbox.io/s/holy-sunset-67b5v?file=/src/App.js
The files are App.js -> roles.js -> infiniteloader.js

Happy to explain what's going on. Let me know.

@ftes
Copy link

ftes commented May 13, 2020

Any help needed to move this PR forward?

}, [pageOffsetKey, pageCountKey])

// Reset page if the key changes
useEffect(() => resetPages(), [resetPages])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't deps be used as the dependencies for this effect?

As also done originally:
https://github.com/gabrielperales/swr/commit/8ba8379d2e6c580ded234385d34ea829be996788#diff-c9d2eb3ea821da85bd697b22fe31edf4R141

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deps itself can't be a dependency cause it is different everytime. You can't spread it either cause react will complain dependency array can't be different length during different render.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree deps itself cannot be a dependency, but I also agree with ftes in saying that I could spread it alongside resetPages (I expect the user to provide a dependency array with the same size every render). Another issue is if we need to reset the pages every time a value used inside the Page component gets updated. In the original API, there is no deps array for the pages, so I use the pages key as a dependency. Maybe we need some clarification about the deps argument from the code owner.

@CurtisBaldwinson
Copy link

Just wanted to let you know that there is still occasionally a stutter on this where the data duplicates once. It's still much better than the click*x number of duplication that happened without this PR.

If anyone is interested in the full fix (acknowledging the awesome work you did here, I'm sure we all really appreciate your help here), there is a PR at #404 that completely addressed the issue (at least for my use case) and with just a few lines of code.

Perhaps it's worth comparing notes on the techniques here and there may be an even more optimal way to achieve this?

@shuding
Copy link
Member

shuding commented Jul 25, 2020

I think we can close this due to the new useSWRInfinite API: #435. It should have solved this problem (and other related ones). As always, thank you for your awesome contribution! 🙏

#243 (comment)

We've been getting a lot of feedback about the old pagination API, and that's why we didn't put it on the documentation publicly and decided to work on a completely new API.

The new API is way more stable and easier to use. We will update the docs once the stable version is released.

@shuding shuding closed this Jul 25, 2020
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

Successfully merging this pull request may close these issues.

None yet

8 participants