diff --git a/src/suspense-query.ts b/src/suspense-query.ts index 56ae13a..d491b6b 100644 --- a/src/suspense-query.ts +++ b/src/suspense-query.ts @@ -12,6 +12,11 @@ interface ISuspenseQueryParams { errorFields?: string[]; } +interface ISuspenseSubqueryOptions { + id: string; + hash: unknown; +} + /** * Run request and cache promise * Sync suspense status between server and client @@ -22,6 +27,11 @@ class SuspenseQuery { */ protected promise: Promise | undefined; + /** + * Subqueries info + */ + protected subqueries: Map }> = new Map(); + /** * Target store */ @@ -136,6 +146,36 @@ class SuspenseQuery { return SuspenseQuery.run(this.promise); }; + /** + * Run subquery + * Re-fetch data from query by hash changes in children components + * NOTE: only client side + */ + public subquery = ( + promise: () => Promise, + options: ISuspenseSubqueryOptions, + ): TReturn | undefined => { + const { id, hash } = options; + const subquery = this.subqueries.get(id); + + // skip first run + if (!subquery) { + this.subqueries.set(id, { hash }); + + return undefined; + } + + if (subquery?.hash === hash) { + return SuspenseQuery.run(subquery?.promise); + } + + const newQuery = promise(); + + this.subqueries.set(id, { hash, promise: newQuery }); + + return SuspenseQuery.run(newQuery); + }; + /** * Change status of promise. * Throw promise to react suspense