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

[Feature Request] - Add option to selectors to scope cache to RecoilRoot #2224

Open
brandonFaf opened this issue Apr 24, 2023 · 6 comments
Open

Comments

@brandonFaf
Copy link

Hello friends,

Request

I would like to suggest an option to allow a selector to be cached respective to a RecoilRoot rather than the application.

Context

From a strictly client side approach, caching globally/application level doesn't seem to cause any problems. However, I am trying to use recoil in a Server Side Rendered application using Nextjs 13. I am seeing an undesired behavior where a selector is not rerun on the server when rendering a page if it has been run because the page has been requested previously. It seems that the cache is not tied to a RecoilRoot, which makes sense based off of the documentation. This is undesireable because it increases the risk of cached data being accessed accidentally or stale data being rendered.

Code Suggestion

I would suggest adding an option to a selector allowing a user to specify if the cache should be tied to a RecoilRoot.

Questions

  1. Is this how recoil is designed to work with SSR?
  2. Is there a reason that I shouldn't try to use recoil with SSR, or Server Components?
@FokkeZB
Copy link

FokkeZB commented Apr 25, 2023

I am seeing an undesired behavior where a selector is not rerun on the server when rendering a page if it has been run because the page has been requested previously.

@brandonFaf can you link to a https://codesandbox.io/ that demonstrates this issue? ❤️

@brandonFaf
Copy link
Author

@FokkeZB
Here is an example repo where you can see the described behavior

There is one dynamic route that is /example/[id].

  1. Make a request to /example/1.
    The first time you will see in the logs of the server:
rendering page with id: 1
running selector: waiting on promise
resolving

**Note: you will only see the suspense fallback show on the client I believe due to this issue

  1. If you refresh the page you will only see in the console:
rendering page with id: 1

You will not see that the selector is running. Since the page isn’t cached (thats why you still see the console log for rendering the page) that means a new RecoilRoot is being rendered Ideally that would mean that the selector would run again.

@drarmstr
Copy link
Contributor

There is a workaround if you want to scope a selector by a Recoil store. You can create an atom with an atom effect that initializes it with the store ID (something like atom({key: 'storeID', effects: [({setSelf, storeID}) => setSelf(storeID)]});), then just depend on that in your selector.

@stevemolitor
Copy link

Thanks @drarmstr!

Would the selector cache memory still be in use on the server, after a request completes?

We just render a single <RecoiRoot> in the top level component of our app. Ideally I'd like to keep selector cache around for the length of a single request, scoped to one user / one <RecoilRoot>, which your suggestion accomplishes. But also I'd like the selector cache data to be eligible for garbage collection once the request completes. One server processes a lot of requests for lots of users, so we don't want stuff hanging out in server memory.

More generally, are there patterns or best practices for using recoil server-side, with SSR or server components? Or is recoil really more designed for client-side usage, even it can be made to work server-side?

Thanks!

@drarmstr
Copy link
Contributor

You can set the cache policy for the selector to be most-recent.

@stevemolitor
Copy link

Thanks @drarmstr!

Would the selector caches be eligible for GC when the server request completes? Or would we have lot of caches of size 1, gradually increasing per request?

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

4 participants