Skip to content

Commit b903d2e

Browse files
thomasballingerConvex, Inc.
authored andcommitted
Opt-in for inconsistent queries with React Query integration (#38200)
At least until consistent queries require only a single round-trip (at which point this option might become a no-op) allow opting in to inconsistent queries since they're faster. GitOrigin-RevId: 6f7a690653d14936326dd7cb05f45cc157eea67a
1 parent f9eccbd commit b903d2e

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

src/index.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,33 @@ function hash(
8787
export interface ConvexQueryClientOptions extends ConvexReactClientOptions {
8888
/** queryClient can also be set later by calling .connect(ReactqueryClient) */
8989
queryClient?: QueryClient;
90+
/**
91+
* opt out of consistent queries, resulting in (for now) faster SSR at the
92+
* cost of potential inconsistency between queries
93+
*
94+
* Why might you need this? Consistency is important when clients expect
95+
* multiple queries to make sense together, e.g. for "client-side joins."
96+
*
97+
* Say you make two queries that your React code expects to be from the same database state:
98+
*
99+
* ```
100+
* const channels = useQuery(api.channels.all)
101+
* const favChannelIds = useQuery(api.channels.favIds');
102+
* const favChannels = (channels && favChannels) ? favChannels.map(c => channels[c]) : []
103+
* ```
104+
*
105+
* During normal client operation, the `api.channels.all` and `api.channels.favIds`
106+
* queries will both return results from the same logical timestamp: as long as these
107+
* queries are written correctly, there will never be a favChannelId for a channel
108+
* not in favChannels.
109+
*
110+
* But during SSR, if this value is set, these two queries may return results
111+
* from different logical timestamps, as they're not just two HTTP requests.
112+
*
113+
* The upside of this is a faster SSR render: the current implementation
114+
* of a consistent SSR render involves two roundtrips instead of one.
115+
*/
116+
dangerouslyUseInconsistentQueriesDuringSSR?: boolean;
90117
}
91118

92119
/**
@@ -112,6 +139,7 @@ export class ConvexQueryClient {
112139
// Only exists during SSR
113140
serverHttpClient?: ConvexHttpClient;
114141
_queryClient: QueryClient | undefined;
142+
ssrQueryMode: "consistent" | "inconsistent";
115143
get queryClient() {
116144
if (!this._queryClient) {
117145
throw new Error(
@@ -131,6 +159,11 @@ export class ConvexQueryClient {
131159
} else {
132160
this.convexClient = client as ConvexReactClient;
133161
}
162+
if (options.dangerouslyUseInconsistentQueriesDuringSSR) {
163+
this.ssrQueryMode = "inconsistent";
164+
} else {
165+
this.ssrQueryMode = "consistent";
166+
}
134167
this.subscriptions = {};
135168
if (options.queryClient) {
136169
this._queryClient = options.queryClient;
@@ -321,7 +354,11 @@ export class ConvexQueryClient {
321354
if (isConvexQuery(context.queryKey)) {
322355
const [_, func, args] = context.queryKey;
323356
if (isServer) {
324-
return await this.serverHttpClient!.consistentQuery(func, args);
357+
if (this.ssrQueryMode === "consistent") {
358+
return await this.serverHttpClient!.consistentQuery(func, args);
359+
} else {
360+
return await this.serverHttpClient!.query(func, args);
361+
}
325362
} else {
326363
return await this.convexClient.query(func, args);
327364
}

0 commit comments

Comments
 (0)