Skip to content

Conversation

rkistner
Copy link
Contributor

@rkistner rkistner commented Mar 18, 2024

This is an alternative approach to #84 - see the PR for the problem statement.

This uses React <Suspense> to wait until the initial query results have loaded before rendering the component. This makes the usePowerSyncWatchedQuery API practically unchanged: Just use const results = usePowerSyncWatchedQuery(...) - but without ever getting "loading" results. Instead, you use Suspense and error boundaries to handle loading states and errors, respectively.

The changes to the demo app are primarily:

  1. Refactor sql-console page to handle loading and error states.
  2. Refactor todo list page to display the list of todos to the left and todos on the right (same as POC: Preloading queries #84).
  3. Place <Suspense/> in the layout.

One caveat is that, by default, you now get a loading spinner (the Suspense fallback) for an instant when navigating. useTransition avoids this, but it's tedious to add to every navigation, and that doesn't handle browser back/forward. Ideally this would be handled by the router, but integrating this with react-router seems tricky. Update: react-router has an experimental option v7_startTransition that does exactly this.

The implementation is based on Relay's useLazyLoadQuery implementation. This approach is called "fetch-on-render", which is typically not recommended for fetching data from a server, since it often causes "waterfall" loading. However, loading from a local database is very fast despite it being asynchronous, so that's not really an issue.

React does make it difficult to implement this pattern. When "suspending" a render, all state is discarded, so you can't keep track of a loading query in the component state. Instead, a "QueryStore" is used here to keep track of watched queries. It uses some workarounds to track queries between the initial suspend and the first actual render. One additional advantage of this approach is that watched queries can now be shared between different components, instead of each re-evaluating the same queries.

@rkistner
Copy link
Contributor Author

Closing - we have a useSuspenseQuery hook now.

@rkistner rkistner closed this Mar 18, 2025
@rkistner rkistner deleted the suspense-poc branch March 18, 2025 11:31
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.

1 participant