@evolu/react 9.0.1-preview.4 → 9.0.1-preview.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,5 +13,3 @@ The Evolu community is on [GitHub Discussions](https://github.com/evoluhq/evolu/
13
13
  To chat with other community members, you can join the [Evolu Discord](https://discord.gg/2J8yyyyxtZ).
14
14
 
15
15
  [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/evoluhq.svg?style=social&label=Follow%20%40evoluhq)](https://twitter.com/evoluhq)
16
-
17
- TODO: remove this line
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export * from "./createUseEvolu.js";
2
2
  export * from "./EvoluContext.js";
3
3
  export * from "./EvoluProvider.js";
4
- export * from "./useAppOwner.js";
5
4
  export * from "./useEvolu.js";
6
5
  export * from "./useEvoluError.js";
6
+ export * from "./useOwner.js";
7
7
  export * from "./useQueries.js";
8
8
  export * from "./useQuery.js";
9
9
  export * from "./useQuerySubscription.js";
10
- export * from "./useSyncState.js";
10
+ export * from "./useIsSsr.js";
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,2BAA2B,CAAC;AAE1C,cAAc,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  export * from "./createUseEvolu.js";
2
2
  export * from "./EvoluContext.js";
3
3
  export * from "./EvoluProvider.js";
4
- export * from "./useAppOwner.js";
5
4
  export * from "./useEvolu.js";
6
5
  export * from "./useEvoluError.js";
6
+ export * from "./useOwner.js";
7
7
  export * from "./useQueries.js";
8
8
  export * from "./useQuery.js";
9
9
  export * from "./useQuerySubscription.js";
10
- export * from "./useSyncState.js";
10
+ // export * from "./useSyncState.js"; TODO: Update it for the owner-api
11
+ export * from "./useIsSsr.js";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Avoiding hydration mismatches.
3
+ *
4
+ * @see https://kurtextrem.de/posts/react-uses-hydration
5
+ */
6
+ export declare const useIsSsr: () => boolean;
7
+ //# sourceMappingURL=useIsSsr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsSsr.d.ts","sourceRoot":"","sources":["../src/useIsSsr.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,eAAO,MAAM,QAAQ,QAAO,OAG3B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { constFalse, constTrue } from "@evolu/common";
2
+ import { useSyncExternalStore } from "react";
3
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
4
+ const emptySubscribe = () => () => { };
5
+ /**
6
+ * Avoiding hydration mismatches.
7
+ *
8
+ * @see https://kurtextrem.de/posts/react-uses-hydration
9
+ */
10
+ export const useIsSsr = () => {
11
+ // TODO: Consider useDeferredValue(isSSRSync);
12
+ return useSyncExternalStore(emptySubscribe, constFalse, constTrue);
13
+ };
@@ -0,0 +1,22 @@
1
+ import { SyncOwner } from "@evolu/common";
2
+ /**
3
+ * React Hook for managing sync owner subscriptions.
4
+ *
5
+ * When the component mounts, it registers the owner for syncing. When the
6
+ * component unmounts or the owner changes, it automatically unregisters.
7
+ *
8
+ * ### Example
9
+ *
10
+ * ```tsx
11
+ * import { useOwner } from "@evolu/react";
12
+ *
13
+ * function MyComponent({ shardOwner }: { shardOwner: SyncOwner | null }) {
14
+ * useOwner(shardOwner);
15
+ *
16
+ * // Component will sync with shardOwner while mounted
17
+ * return <div>Syncing with shard...</div>;
18
+ * }
19
+ * ```
20
+ */
21
+ export declare const useOwner: (owner: SyncOwner | null) => void;
22
+ //# sourceMappingURL=useOwner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOwner.d.ts","sourceRoot":"","sources":["../src/useOwner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,SAAS,GAAG,IAAI,KAAG,IAOlD,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { useEffect } from "react";
2
+ import { useEvolu } from "./useEvolu.js";
3
+ /**
4
+ * React Hook for managing sync owner subscriptions.
5
+ *
6
+ * When the component mounts, it registers the owner for syncing. When the
7
+ * component unmounts or the owner changes, it automatically unregisters.
8
+ *
9
+ * ### Example
10
+ *
11
+ * ```tsx
12
+ * import { useOwner } from "@evolu/react";
13
+ *
14
+ * function MyComponent({ shardOwner }: { shardOwner: SyncOwner | null }) {
15
+ * useOwner(shardOwner);
16
+ *
17
+ * // Component will sync with shardOwner while mounted
18
+ * return <div>Syncing with shard...</div>;
19
+ * }
20
+ * ```
21
+ */
22
+ export const useOwner = (owner) => {
23
+ const evolu = useEvolu();
24
+ useEffect(() => {
25
+ if (owner == null)
26
+ return;
27
+ return evolu.useOwner(owner);
28
+ }, [evolu, owner]);
29
+ };
@@ -1,5 +1,9 @@
1
1
  import { Queries, QueriesToQueryRows, QueriesToQueryRowsPromises, Row } from "@evolu/common/evolu";
2
- /** The same as {@link useQuery}, but for many queries. */
2
+ /**
3
+ * The same as {@link useQuery}, but for many queries.
4
+ *
5
+ * The number of queries must remain stable across renders.
6
+ */
3
7
  export declare const useQueries: <R extends Row, Q extends Queries<R>, OQ extends Queries<R>>(queries: [...Q], options?: Partial<{
4
8
  /** Queries that should be only loaded, not subscribed to. */
5
9
  readonly once: [...OQ];
@@ -1 +1 @@
1
- {"version":3,"file":"useQueries.d.ts","sourceRoot":"","sources":["../src/useQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,kBAAkB,EAClB,0BAA0B,EAC1B,GAAG,EACJ,MAAM,qBAAqB,CAAC;AAO7B,0DAA0D;AAC1D,eAAO,MAAM,UAAU,GACrB,CAAC,SAAS,GAAG,EACb,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EACpB,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,EAErB,SAAS,CAAC,GAAG,CAAC,CAAC,EACf,UAAS,OAAO,CAAC;IACf,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IAEvB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,CACjB,GAAG,0BAA0B,CAAC,CAAC,CAAC,EAChC,GAAG,0BAA0B,CAAC,EAAE,CAAC,CAClC,CAAC;CACH,CAAM,KACN,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAgBtD,CAAC"}
1
+ {"version":3,"file":"useQueries.d.ts","sourceRoot":"","sources":["../src/useQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,kBAAkB,EAClB,0BAA0B,EAC1B,GAAG,EACJ,MAAM,qBAAqB,CAAC;AAO7B;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,CAAC,SAAS,GAAG,EACb,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EACpB,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,EAErB,SAAS,CAAC,GAAG,CAAC,CAAC,EACf,UAAS,OAAO,CAAC;IACf,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IAEvB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,CACjB,GAAG,0BAA0B,CAAC,CAAC,CAAC,EAChC,GAAG,0BAA0B,CAAC,EAAE,CAAC,CAClC,CAAC;CACH,CAAM,KACN,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAkBtD,CAAC"}
@@ -1,25 +1,31 @@
1
1
  import { use, useRef } from "react";
2
2
  import { useEvolu } from "./useEvolu.js";
3
3
  import { useQuerySubscription } from "./useQuerySubscription.js";
4
- import { useWasSSR } from "./useWasSSR.js";
5
- /** The same as {@link useQuery}, but for many queries. */
4
+ import { useIsSsr } from "./useIsSsr.js";
5
+ /**
6
+ * The same as {@link useQuery}, but for many queries.
7
+ *
8
+ * The number of queries must remain stable across renders.
9
+ */
6
10
  export const useQueries = (queries, options = {}) => {
7
11
  const evolu = useEvolu();
8
12
  const once = useRef(options).current.once;
9
13
  const allQueries = once ? queries.concat(once) : queries;
10
- const wasSSR = useWasSSR();
14
+ const wasSSR = useIsSsr();
11
15
  if (wasSSR) {
12
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
13
16
  if (!options.promises)
14
- evolu.loadQueries(allQueries);
17
+ void evolu.loadQueries(allQueries);
15
18
  }
16
19
  else {
17
20
  if (options.promises)
18
21
  options.promises.map(use);
22
+ // No waterfall: loadQuery batches all queries in the same microtask,
23
+ // so React suspends once and all promises resolve together.
19
24
  else
20
25
  evolu.loadQueries(allQueries).map(use);
21
26
  }
22
27
  return allQueries.map((query, i) =>
28
+ // Safe until the number of queries is stable.
23
29
  // eslint-disable-next-line react-hooks/rules-of-hooks
24
30
  useQuerySubscription(query, { once: i > queries.length - 1 }));
25
31
  };
@@ -7,6 +7,10 @@ import { Query, QueryRows, Row } from "@evolu/common/evolu";
7
7
  * {@link useQuery} blocks rendering until loading is completed. To avoid loading
8
8
  * waterfall with more queries, use {@link useQueries}.
9
9
  *
10
+ * The `promise` option allows preloading queries before rendering, which can be
11
+ * useful for complex queries that might take noticeable time even with local
12
+ * data. However, this is rarely needed as local queries are typically fast.
13
+ *
10
14
  * ### Example
11
15
  *
12
16
  * ```ts
@@ -19,12 +23,8 @@ import { Query, QueryRows, Row } from "@evolu/common/evolu";
19
23
  * // Get all rows, but without subscribing to changes.
20
24
  * const rows = useQuery(allTodos, { once: true });
21
25
  *
22
- * // Prefetch rows.
23
- * const allTodos = evolu.createQuery((db) =>
24
- * db.selectFrom("todo").selectAll(),
25
- * );
26
+ * // Preload a query (rarely needed).
26
27
  * const allTodosPromise = evolu.loadQuery(allTodos);
27
- * // Use prefetched rows.
28
28
  * const rows = useQuery(allTodos, { promise: allTodosPromise });
29
29
  * ```
30
30
  */
@@ -1 +1 @@
1
- {"version":3,"file":"useQuery.d.ts","sourceRoot":"","sources":["../src/useQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAO5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,GAAG,EACpC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,UAAS,OAAO,CAAC;IACf,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC,CAAM,KACN,SAAS,CAAC,CAAC,CASb,CAAC"}
1
+ {"version":3,"file":"useQuery.d.ts","sourceRoot":"","sources":["../src/useQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAO5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,GAAG,EACpC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,UAAS,OAAO,CAAC;IACf,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC,CAAM,KACN,SAAS,CAAC,CAAC,CAWb,CAAC"}
package/dist/useQuery.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { use } from "react";
2
2
  import { useEvolu } from "./useEvolu.js";
3
3
  import { useQuerySubscription } from "./useQuerySubscription.js";
4
- import { useWasSSR } from "./useWasSSR.js";
4
+ import { useIsSsr } from "./useIsSsr.js";
5
5
  /**
6
6
  * Load and subscribe to the Query, and return an object with `rows` and `row`
7
7
  * properties that are automatically updated when data changes.
@@ -10,6 +10,10 @@ import { useWasSSR } from "./useWasSSR.js";
10
10
  * {@link useQuery} blocks rendering until loading is completed. To avoid loading
11
11
  * waterfall with more queries, use {@link useQueries}.
12
12
  *
13
+ * The `promise` option allows preloading queries before rendering, which can be
14
+ * useful for complex queries that might take noticeable time even with local
15
+ * data. However, this is rarely needed as local queries are typically fast.
16
+ *
13
17
  * ### Example
14
18
  *
15
19
  * ```ts
@@ -22,19 +26,15 @@ import { useWasSSR } from "./useWasSSR.js";
22
26
  * // Get all rows, but without subscribing to changes.
23
27
  * const rows = useQuery(allTodos, { once: true });
24
28
  *
25
- * // Prefetch rows.
26
- * const allTodos = evolu.createQuery((db) =>
27
- * db.selectFrom("todo").selectAll(),
28
- * );
29
+ * // Preload a query (rarely needed).
29
30
  * const allTodosPromise = evolu.loadQuery(allTodos);
30
- * // Use prefetched rows.
31
31
  * const rows = useQuery(allTodos, { promise: allTodosPromise });
32
32
  * ```
33
33
  */
34
34
  export const useQuery = (query, options = {}) => {
35
35
  const evolu = useEvolu();
36
- const wasSSR = useWasSSR();
37
- if (wasSSR) {
36
+ const isSSR = useIsSsr();
37
+ if (isSSR) {
38
38
  if (!options.promise)
39
39
  void evolu.loadQuery(query);
40
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useSyncState.d.ts","sourceRoot":"","sources":["../src/useSyncState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,qBAAqB,CAAC;AAIlE,8CAA8C;AAC9C,eAAO,MAAM,YAAY,QAAO,SAO/B,CAAC"}
1
+ {"version":3,"file":"useSyncState.d.ts","sourceRoot":"","sources":["../src/useSyncState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,8CAA8C;AAC9C,eAAO,MAAM,YAAY,QAAO,SAQ/B,CAAC"}
@@ -1,8 +1,11 @@
1
- import { initialSyncState } from "@evolu/common/evolu";
2
- import { useSyncExternalStore } from "react";
3
1
  import { useEvolu } from "./useEvolu.js";
4
2
  /** Subscribe to {@link SyncState} changes. */
5
3
  export const useSyncState = () => {
6
- const evolu = useEvolu();
7
- return useSyncExternalStore(evolu.subscribeSyncState, evolu.getSyncState, () => initialSyncState);
4
+ const _evolu = useEvolu();
5
+ // return useSyncExternalStore(
6
+ // evolu.subscribeSyncState,
7
+ // evolu.getSyncState,
8
+ // () => initialSyncState,
9
+ // );
10
+ throw new Error("TODO");
8
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolu/react",
3
- "version": "9.0.1-preview.4",
3
+ "version": "9.0.1-preview.6",
4
4
  "description": "Evolu for React",
5
5
  "keywords": [
6
6
  "evolu",
@@ -30,16 +30,18 @@
30
30
  "README.md"
31
31
  ],
32
32
  "devDependencies": {
33
- "@types/react-dom": "^19.1.7",
34
- "react": "^19.1.1",
33
+ "@types/react": "~19.1.13",
34
+ "@types/react-dom": "~19.1.9",
35
+ "react": "19.1.0",
36
+ "shx": "^0.4.0",
35
37
  "typescript": "^5.9.2",
36
- "vitest": "^3.2.3",
37
- "@evolu/common": "6.0.1-preview.18",
38
+ "vitest": "^4.0.4",
39
+ "@evolu/common": "6.0.1-preview.22",
38
40
  "@evolu/tsconfig": "0.0.2"
39
41
  },
40
42
  "peerDependencies": {
41
- "@evolu/common": "^6.0.1-preview.18",
42
- "react": "^19.0.0"
43
+ "@evolu/common": "^6.0.1-preview.22",
44
+ "react": ">=19"
43
45
  },
44
46
  "publishConfig": {
45
47
  "access": "public"
package/src/index.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export * from "./createUseEvolu.js";
2
2
  export * from "./EvoluContext.js";
3
3
  export * from "./EvoluProvider.js";
4
- export * from "./useAppOwner.js";
5
4
  export * from "./useEvolu.js";
6
5
  export * from "./useEvoluError.js";
6
+ export * from "./useOwner.js";
7
7
  export * from "./useQueries.js";
8
8
  export * from "./useQuery.js";
9
9
  export * from "./useQuerySubscription.js";
10
- export * from "./useSyncState.js";
10
+ // export * from "./useSyncState.js"; TODO: Update it for the owner-api
11
+ export * from "./useIsSsr.js";
@@ -0,0 +1,15 @@
1
+ import { constFalse, constTrue } from "@evolu/common";
2
+ import { useSyncExternalStore } from "react";
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
5
+ const emptySubscribe = () => () => {};
6
+
7
+ /**
8
+ * Avoiding hydration mismatches.
9
+ *
10
+ * @see https://kurtextrem.de/posts/react-uses-hydration
11
+ */
12
+ export const useIsSsr = (): boolean => {
13
+ // TODO: Consider useDeferredValue(isSSRSync);
14
+ return useSyncExternalStore(emptySubscribe, constFalse, constTrue);
15
+ };
@@ -0,0 +1,31 @@
1
+ import { SyncOwner } from "@evolu/common";
2
+ import { useEffect } from "react";
3
+ import { useEvolu } from "./useEvolu.js";
4
+
5
+ /**
6
+ * React Hook for managing sync owner subscriptions.
7
+ *
8
+ * When the component mounts, it registers the owner for syncing. When the
9
+ * component unmounts or the owner changes, it automatically unregisters.
10
+ *
11
+ * ### Example
12
+ *
13
+ * ```tsx
14
+ * import { useOwner } from "@evolu/react";
15
+ *
16
+ * function MyComponent({ shardOwner }: { shardOwner: SyncOwner | null }) {
17
+ * useOwner(shardOwner);
18
+ *
19
+ * // Component will sync with shardOwner while mounted
20
+ * return <div>Syncing with shard...</div>;
21
+ * }
22
+ * ```
23
+ */
24
+ export const useOwner = (owner: SyncOwner | null): void => {
25
+ const evolu = useEvolu();
26
+
27
+ useEffect(() => {
28
+ if (owner == null) return;
29
+ return evolu.useOwner(owner);
30
+ }, [evolu, owner]);
31
+ };
package/src/useQueries.ts CHANGED
@@ -8,9 +8,13 @@ import { use, useRef } from "react";
8
8
  import { useEvolu } from "./useEvolu.js";
9
9
  import type { useQuery } from "./useQuery.js";
10
10
  import { useQuerySubscription } from "./useQuerySubscription.js";
11
- import { useWasSSR } from "./useWasSSR.js";
11
+ import { useIsSsr } from "./useIsSsr.js";
12
12
 
13
- /** The same as {@link useQuery}, but for many queries. */
13
+ /**
14
+ * The same as {@link useQuery}, but for many queries.
15
+ *
16
+ * The number of queries must remain stable across renders.
17
+ */
14
18
  export const useQueries = <
15
19
  R extends Row,
16
20
  Q extends Queries<R>,
@@ -31,15 +35,17 @@ export const useQueries = <
31
35
  const evolu = useEvolu();
32
36
  const once = useRef(options).current.once;
33
37
  const allQueries = once ? queries.concat(once) : queries;
34
- const wasSSR = useWasSSR();
38
+ const wasSSR = useIsSsr();
35
39
  if (wasSSR) {
36
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
37
- if (!options.promises) evolu.loadQueries(allQueries);
40
+ if (!options.promises) void evolu.loadQueries(allQueries);
38
41
  } else {
39
42
  if (options.promises) options.promises.map(use);
43
+ // No waterfall: loadQuery batches all queries in the same microtask,
44
+ // so React suspends once and all promises resolve together.
40
45
  else evolu.loadQueries(allQueries).map(use);
41
46
  }
42
47
  return allQueries.map((query, i) =>
48
+ // Safe until the number of queries is stable.
43
49
  // eslint-disable-next-line react-hooks/rules-of-hooks
44
50
  useQuerySubscription(query, { once: i > queries.length - 1 }),
45
51
  ) as never;
package/src/useQuery.ts CHANGED
@@ -3,7 +3,7 @@ import { use } from "react";
3
3
  import { useEvolu } from "./useEvolu.js";
4
4
  import type { useQueries } from "./useQueries.js";
5
5
  import { useQuerySubscription } from "./useQuerySubscription.js";
6
- import { useWasSSR } from "./useWasSSR.js";
6
+ import { useIsSsr } from "./useIsSsr.js";
7
7
 
8
8
  /**
9
9
  * Load and subscribe to the Query, and return an object with `rows` and `row`
@@ -13,6 +13,10 @@ import { useWasSSR } from "./useWasSSR.js";
13
13
  * {@link useQuery} blocks rendering until loading is completed. To avoid loading
14
14
  * waterfall with more queries, use {@link useQueries}.
15
15
  *
16
+ * The `promise` option allows preloading queries before rendering, which can be
17
+ * useful for complex queries that might take noticeable time even with local
18
+ * data. However, this is rarely needed as local queries are typically fast.
19
+ *
16
20
  * ### Example
17
21
  *
18
22
  * ```ts
@@ -25,12 +29,8 @@ import { useWasSSR } from "./useWasSSR.js";
25
29
  * // Get all rows, but without subscribing to changes.
26
30
  * const rows = useQuery(allTodos, { once: true });
27
31
  *
28
- * // Prefetch rows.
29
- * const allTodos = evolu.createQuery((db) =>
30
- * db.selectFrom("todo").selectAll(),
31
- * );
32
+ * // Preload a query (rarely needed).
32
33
  * const allTodosPromise = evolu.loadQuery(allTodos);
33
- * // Use prefetched rows.
34
34
  * const rows = useQuery(allTodos, { promise: allTodosPromise });
35
35
  * ```
36
36
  */
@@ -45,11 +45,13 @@ export const useQuery = <R extends Row>(
45
45
  }> = {},
46
46
  ): QueryRows<R> => {
47
47
  const evolu = useEvolu();
48
- const wasSSR = useWasSSR();
49
- if (wasSSR) {
48
+ const isSSR = useIsSsr();
49
+
50
+ if (isSSR) {
50
51
  if (!options.promise) void evolu.loadQuery(query);
51
52
  } else {
52
53
  use(options.promise ?? evolu.loadQuery(query));
53
54
  }
55
+
54
56
  return useQuerySubscription(query, options);
55
57
  };
@@ -1,13 +1,13 @@
1
- import { SyncState, initialSyncState } from "@evolu/common/evolu";
2
- import { useSyncExternalStore } from "react";
1
+ import { SyncState } from "@evolu/common/evolu";
3
2
  import { useEvolu } from "./useEvolu.js";
4
3
 
5
4
  /** Subscribe to {@link SyncState} changes. */
6
5
  export const useSyncState = (): SyncState => {
7
- const evolu = useEvolu();
8
- return useSyncExternalStore(
9
- evolu.subscribeSyncState,
10
- evolu.getSyncState,
11
- () => initialSyncState,
12
- );
6
+ const _evolu = useEvolu();
7
+ // return useSyncExternalStore(
8
+ // evolu.subscribeSyncState,
9
+ // evolu.getSyncState,
10
+ // () => initialSyncState,
11
+ // );
12
+ throw new Error("TODO");
13
13
  };
@@ -1,4 +0,0 @@
1
- import { AppOwner } from "@evolu/common";
2
- /** Subscribe to {@link AppOwner} changes. */
3
- export declare const useAppOwner: () => AppOwner | null;
4
- //# sourceMappingURL=useAppOwner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAppOwner.d.ts","sourceRoot":"","sources":["../src/useAppOwner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAC;AAIpD,6CAA6C;AAC7C,eAAO,MAAM,WAAW,QAAO,QAAQ,GAAG,IAOzC,CAAC"}
@@ -1,8 +0,0 @@
1
- import { constNull } from "@evolu/common";
2
- import { useSyncExternalStore } from "react";
3
- import { useEvolu } from "./useEvolu.js";
4
- /** Subscribe to {@link AppOwner} changes. */
5
- export const useAppOwner = () => {
6
- const evolu = useEvolu();
7
- return useSyncExternalStore(evolu.subscribeAppOwner, evolu.getAppOwner, constNull);
8
- };
@@ -1,6 +0,0 @@
1
- /**
2
- * "Unlike the typeof window hack, this ensures that the server and hydration
3
- * sees the same thing."
4
- */
5
- export declare const useWasSSR: () => boolean;
6
- //# sourceMappingURL=useWasSSR.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useWasSSR.d.ts","sourceRoot":"","sources":["../src/useWasSSR.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,eAAO,MAAM,SAAS,QAAO,OAO5B,CAAC"}
package/dist/useWasSSR.js DELETED
@@ -1,11 +0,0 @@
1
- import { useRef, useSyncExternalStore } from "react";
2
- // eslint-disable-next-line @typescript-eslint/no-empty-function
3
- const emptySubscribe = () => () => { };
4
- /**
5
- * "Unlike the typeof window hack, this ensures that the server and hydration
6
- * sees the same thing."
7
- */
8
- export const useWasSSR = () => {
9
- const ref = useRef(false);
10
- return useSyncExternalStore(emptySubscribe, () => ref.current, () => (ref.current = true));
11
- };
@@ -1,13 +0,0 @@
1
- import { AppOwner, constNull } from "@evolu/common";
2
- import { useSyncExternalStore } from "react";
3
- import { useEvolu } from "./useEvolu.js";
4
-
5
- /** Subscribe to {@link AppOwner} changes. */
6
- export const useAppOwner = (): AppOwner | null => {
7
- const evolu = useEvolu();
8
- return useSyncExternalStore(
9
- evolu.subscribeAppOwner,
10
- evolu.getAppOwner,
11
- constNull,
12
- );
13
- };
package/src/useWasSSR.ts DELETED
@@ -1,17 +0,0 @@
1
- import { useRef, useSyncExternalStore } from "react";
2
-
3
- // eslint-disable-next-line @typescript-eslint/no-empty-function
4
- const emptySubscribe = () => () => {};
5
-
6
- /**
7
- * "Unlike the typeof window hack, this ensures that the server and hydration
8
- * sees the same thing."
9
- */
10
- export const useWasSSR = (): boolean => {
11
- const ref = useRef(false);
12
- return useSyncExternalStore(
13
- emptySubscribe,
14
- () => ref.current,
15
- () => (ref.current = true),
16
- );
17
- };