POC: Suspense for usePowerSyncWatchedQuery #100
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 theusePowerSyncWatchedQuery
API practically unchanged: Just useconst 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:
<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 optionv7_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.