pglite icon indicating copy to clipboard operation
pglite copied to clipboard

[Discussion] `useLiveQuery` with cached results.

Open thruflo opened this issue 10 months ago • 1 comments

Building a little bit on https://github.com/electric-sql/pglite/issues/544, I propose an optional mechanism for useLiveQuery to re-use the previous query results when re-rendering a component.

My use case was as follows:

  • two screens in an app
  • the first screen loads some listings using a live query
  • navigate to the second screen
  • navigate back to the first

Even with a small query, if I use the IDB filesystem, I get a noticeable flash of missing content -> content when I navigate back to the first screen. Because useLiveQuery always starts undefined and then async populates the results.

What I'd like is, in this type of circumstance, is to be able to say "hey, live query, cache the query results and use the latest cache as the default when rendering". This way, the user sees content immediately when navigating back to the page.

There may be downsides when the content underneath the live query has changed, such as listings jumping around. But this can be mitigated by (1) being an optional mechanism or (2) possibly considering ways to invalidate the cache on changes.

I imagine that this could be implemented using an option, such as {cacheResults: true}. Or it could possibly be a special value for default if using option syntax to implement #544, such as {default: live.CACHE}.


I guess the other approach here is to be able to keep the liveQuery going behind the component lifecycle.

I.e.: instead of teardown on unmount, somehow mark the query as having a ttl in the background and then using the same instance of a live query when re-rendering with the same key. This could provide the best of both worlds, in that results are instant and uptodate when navigating back.

Perhaps we would need a queryKey or perhaps we can dedupe by the actual query string and params anyway? Perhaps we would need an unMountedTTL or something? If we found a way, it would perhaps be similar to the idea that shape subscriptions go on in the background unless explicitly stopped.

thruflo avatar Feb 17 '25 09:02 thruflo

I like this.

There is another option in this situation (that we use in linearlite) that we need to document better. You can create the liveQuery in the React Route / TanStack Route loader, then pass it to the component and useLiveQuery(myLiveQueryInstance). This is this call signature:

https://github.com/electric-sql/pglite/blob/0c7454d1cef9725c6dc3f1e26352016c6145c3be/packages/pglite-react/src/hooks.ts#L106-L108

This ensures that the query has done its initial load before the route changes to the navigated to screen.

We should add caching though! I wander if there is a way to do it in a global way 🤔

samwillis avatar Feb 17 '25 14:02 samwillis