@raf-query/react 0.7.12 → 0.8.0

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/CHANGELOG.md CHANGED
@@ -1,15 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.0](https://github.com/KATT/raf-query/compare/0.7.12...0.8.0) (2026-10-15)
4
+
5
+ ### ⚠ BREAKING CHANGES
6
+
7
+ * ensure and fetch return a QueryHandleWithData ([#142](https://github.com/KATT/raf-query/issues/142))
8
+
9
+ ### Features
10
+
11
+ * ensure and fetch return a QueryHandleWithData ([#142](https://github.com/KATT/raf-query/issues/142)) ([504cd2a](https://github.com/KATT/raf-query/commit/504cd2a19e04b614eb648f02b256128c4eb31d38))
12
+
13
+ ### Miscellaneous Chores
14
+
15
+ * group experiments under `.experimental/<topic>/` ([#137](https://github.com/KATT/raf-query/issues/137)) ([52ce752](https://github.com/KATT/raf-query/commit/52ce7522223346e82687338d6ac6d34f793b6fcf))
16
+
3
17
  ## [0.7.12](https://github.com/KATT/raf-query/compare/0.7.11...0.7.12) (2026-10-15)
4
18
 
5
- * add knip with every issue type as an error ([#129](https://github.com/KATT/raf-query/issues/129)) ([603719d](https://github.com/KATT/raf-query/commit/603719dcb834312d4a813ecae865df7d56faf8c5))
6
- * cache Next.js Turbopack builds ([#128](https://github.com/KATT/raf-query/issues/128)) ([667b38f](https://github.com/KATT/raf-query/commit/667b38ff5728dad3fdad6d90445aea480cfbd063))
7
- * explain how a route loads its data on the homepage ([#121](https://github.com/KATT/raf-query/issues/121)) ([ec1d6ef](https://github.com/KATT/raf-query/commit/ec1d6efdad75ea2d05dd56790e5e980756afea13))
8
- * frame the cache as async data, not server-state-only ([#126](https://github.com/KATT/raf-query/issues/126)) ([db9ba02](https://github.com/KATT/raf-query/commit/db9ba02995aa01cadacb2739fd258de3c920d440))
19
+ - add knip with every issue type as an error ([#129](https://github.com/KATT/raf-query/issues/129)) ([603719d](https://github.com/KATT/raf-query/commit/603719dcb834312d4a813ecae865df7d56faf8c5))
20
+ - cache Next.js Turbopack builds ([#128](https://github.com/KATT/raf-query/issues/128)) ([667b38f](https://github.com/KATT/raf-query/commit/667b38ff5728dad3fdad6d90445aea480cfbd063))
21
+ - explain how a route loads its data on the homepage ([#121](https://github.com/KATT/raf-query/issues/121)) ([ec1d6ef](https://github.com/KATT/raf-query/commit/ec1d6efdad75ea2d05dd56790e5e980756afea13))
22
+ - frame the cache as async data, not server-state-only ([#126](https://github.com/KATT/raf-query/issues/126)) ([db9ba02](https://github.com/KATT/raf-query/commit/db9ba02995aa01cadacb2739fd258de3c920d440))
9
23
 
10
24
  ### Features
11
25
 
12
- * **examples:** reinstall shadcn on Base UI without Radix ([#125](https://github.com/KATT/raf-query/issues/125)) ([7c13ef3](https://github.com/KATT/raf-query/commit/7c13ef379dc297edbbe160516b26916d465a48d1))
26
+ - **examples:** reinstall shadcn on Base UI without Radix ([#125](https://github.com/KATT/raf-query/issues/125)) ([7c13ef3](https://github.com/KATT/raf-query/commit/7c13ef379dc297edbbe160516b26916d465a48d1))
13
27
 
14
28
  ## [0.7.11](https://github.com/KATT/raf-query/compare/0.7.10...0.7.11) (2026-10-14)
15
29
 
package/README.md CHANGED
@@ -19,6 +19,7 @@ npm install @raf-query/react
19
19
 
20
20
  ```tsx
21
21
  import { queryOptions, useQuery } from "@raf-query/react";
22
+ import { use } from "react";
22
23
 
23
24
  export function postQuery(input: { slug: string }) {
24
25
  return queryOptions({
@@ -40,7 +41,7 @@ export const Route = createFileRoute("/posts/$slug")({
40
41
  // …and the component reads it.
41
42
  function PostPage() {
42
43
  const [post] = useQuery(postQuery, Route.useLoaderData().post);
43
- return <h1>{post.title}</h1>;
44
+ return <h1>{use(post).title}</h1>;
44
45
  }
45
46
  ```
46
47
 
package/dist/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { DataOf, DehydrateOptions, DehydratedState, EnsuredQueryHandle, HydrateOptions, InputArgs, InputOf, LoadOptions, PagedQueryFactory, Query, QueryCache, QueryFactory, QueryHandle } from "@raf-query/core";
1
+ import { DataOf, DehydrateOptions, DehydratedState, HydrateOptions, InputArgs, InputOf, LoadOptions, PagedQueryFactory, Query, QueryCache, QueryFactory, QueryHandle, QueryHandleWithData } from "@raf-query/core";
2
2
  import { Effect, Layer } from "effect";
3
3
  //#region src/client.d.ts
4
4
  export interface QueryClientConfig<TServices = never> extends QueryCache.Config {
@@ -47,22 +47,21 @@ export declare class QueryClient<TServices = never> {
47
47
  */
48
48
  prefetch<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): QueryHandle<TFactory>;
49
49
  /**
50
- * Start a query and wait for it on a cache miss. Rejects if that request
51
- * fails. Stale cached data resolves immediately and revalidates in the
52
- * browser. The handle is marked `ensured`, so `useQuery` returns its data
53
- * directly.
50
+ * {@link fetch} without waiting on stale data: start a query and wait for
51
+ * it on a cache miss. Stale cached data resolves immediately and
52
+ * revalidates in the browser. Rejects if that request fails.
54
53
  */
55
- ensure<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<EnsuredQueryHandle<TFactory>>;
54
+ ensure<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<QueryHandleWithData<TFactory>>;
56
55
  /** {@link ensure}, loading `options.pages` pages of a paged query. */
57
- ensure<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<EnsuredQueryHandle<TFactory>>;
56
+ ensure<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<QueryHandleWithData<TFactory>>;
58
57
  /**
59
- * Start a query and resolve to its data. Waits on a cache miss and on
60
- * stale data (on the server, only invalidated data), so the data is fresh.
61
- * Rejects if that request fails.
58
+ * Start a query and resolve to a handle holding its data. Waits on a cache
59
+ * miss and on stale data (on the server, only invalidated data), so the
60
+ * data is fresh. Rejects if that request fails.
62
61
  */
63
- fetch<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<DataOf<TFactory>>;
62
+ fetch<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<QueryHandleWithData<TFactory>>;
64
63
  /** {@link fetch}, loading `options.pages` pages of a paged query. */
65
- fetch<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<DataOf<TFactory>>;
64
+ fetch<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<QueryHandleWithData<TFactory>>;
66
65
  /**
67
66
  * Mark queries stale and refetch the ones being read. Resolves once those
68
67
  * refetches settle, so an action stays pending until fresh data is on
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { QueryClient, QueryClientConfig, dehydrate, hydrate } from "./client.mjs
2
2
  import { Settled, allKeyed } from "./all-keyed.mjs";
3
3
  import { QueryClientProvider, useQueryClient } from "./provider.mjs";
4
4
  import { useIsFetching } from "./use-is-fetching.mjs";
5
- import { HasTypedError, PagingControls, QueryControls, ThrowsOnError, UseEnsuredQueryResult, UseQueryControls, UseQueryOptions, UseQueryResult, UseQueryThrowOptions, useQuery } from "./use-query.mjs";
5
+ import { HasTypedError, PagingControls, QueryControls, ThrowsOnError, UseQueryControls, UseQueryOptions, UseQueryResult, UseQueryThrowOptions, useQuery } from "./use-query.mjs";
6
6
  import { useWaterfall } from "./use-waterfall.mjs";
7
7
  export * from "@raf-query/core";
8
- export { type HasTypedError, type PagingControls, QueryClient, type QueryClientConfig, QueryClientProvider, type QueryControls, type Settled, type ThrowsOnError, type UseEnsuredQueryResult, type UseQueryControls, type UseQueryOptions, type UseQueryResult, type UseQueryThrowOptions, allKeyed, dehydrate, hydrate, useIsFetching, useQuery, useQueryClient, useWaterfall };
8
+ export { type HasTypedError, type PagingControls, QueryClient, type QueryClientConfig, QueryClientProvider, type QueryControls, type Settled, type ThrowsOnError, type UseQueryControls, type UseQueryOptions, type UseQueryResult, type UseQueryThrowOptions, allKeyed, dehydrate, hydrate, useIsFetching, useQuery, useQueryClient, useWaterfall };
@@ -1,16 +1,17 @@
1
1
  import { QueryClient } from "./client.mjs";
2
- import { DehydrateOptions, DehydratedState, EnsuredQueryHandle, HydrateOptions, QueryHandle } from "@raf-query/core";
2
+ import { DehydrateOptions, DehydratedState, HydrateOptions, QueryHandle } from "@raf-query/core";
3
3
  import { AnyRouter } from "@tanstack/react-router";
4
4
  //#region src/tanstack-router-shared.d.ts
5
5
  declare module "@tanstack/react-router" {
6
6
  interface SerializableExtensions {
7
7
  /**
8
- * Handles are `{ key, input, ensured? }`, which the router's serializer
9
- * sends as is. Its type check can't see that on its own: keys are
8
+ * Handles are `{ key, input, data? }`, which the router's serializer
9
+ * sends as is (`data` is dehydrated anyway, so it is serializable). Its
10
+ * type check can't see that on its own: keys are
10
11
  * `ReadonlyArray<unknown>`, and the handle type names its factory.
11
12
  * So `beforeLoad` can put handles in route context.
12
13
  */
13
- rafQueryHandle: EnsuredQueryHandle | QueryHandle;
14
+ rafQueryHandle: QueryHandle;
14
15
  }
15
16
  }
16
17
  export interface RouterIntegrationOptions<TRouter extends AnyRouter> {
@@ -1,4 +1,4 @@
1
- import { DataOf, EnsuredQueryHandle, ErrorOf, InputOf, IsPaged, QueryFactory, QueryHandle, QueryKey, QueryObserver } from "@raf-query/core";
1
+ import { DataOf, ErrorOf, InputOf, IsPaged, QueryFactory, QueryHandle, QueryKey, QueryObserver } from "@raf-query/core";
2
2
  import { Result } from "effect";
3
3
  //#region src/use-query.d.ts
4
4
  /** `refetchInterval`, `refetchOnWindowFocus`, `refetchOnReconnect`, `whilePending`. */
@@ -63,8 +63,6 @@ export type HasTypedError<TFactory extends QueryFactory> = unknown extends Error
63
63
  */
64
64
  export type ThrowsOnError<TFactory extends QueryFactory, TThrow extends boolean | undefined> = HasTypedError<TFactory> extends false ? true : TThrow extends boolean ? TThrow : false;
65
65
  export type UseQueryResult<TFactory extends QueryFactory, TThrow extends boolean | undefined = undefined> = ThrowsOnError<TFactory, TThrow> extends true ? readonly [promise: Promise<DataOf<TFactory>>, controls: UseQueryControls<TFactory>] : readonly [promise: Promise<Result.Result<DataOf<TFactory>, ErrorOf<TFactory>>>, controls: UseQueryControls<TFactory>];
66
- /** {@link useQuery}'s result for a handle from `ensure`. */
67
- export type UseEnsuredQueryResult<TFactory extends QueryFactory, TThrow extends boolean | undefined = undefined> = ThrowsOnError<TFactory, TThrow> extends true ? readonly [data: DataOf<TFactory>, controls: UseQueryControls<TFactory>] : readonly [result: Result.Result<DataOf<TFactory>, ErrorOf<TFactory>>, controls: UseQueryControls<TFactory>];
68
66
  /**
69
67
  * Read the query a handle points at. Returns a promise to unwrap with
70
68
  * `use()` and the query's controls:
@@ -89,19 +87,11 @@ export type UseEnsuredQueryResult<TFactory extends QueryFactory, TThrow extends
89
87
  * The component re-renders when the promise changes, and when a control it
90
88
  * has read changes; changes to controls it never reads are skipped.
91
89
  *
92
- * A handle from `ensure` had its data loaded before the route rendered, so
93
- * the hook returns the data (or `Result`) itself:
94
- *
95
- * ```tsx
96
- * const [post, postState] = useQuery(postQuery, loaderData.post);
97
- * ```
98
- *
99
- * If that entry has lost its data since (garbage-collected, `reset`), the
100
- * hook suspends until it is refetched.
90
+ * A handle from `ensure` or `fetch` reads the same way: the hook reads the
91
+ * live entry, not the handle's `data` snapshot, and its promise is already
92
+ * fulfilled unless the entry has lost its data since (garbage-collected,
93
+ * `reset`).
101
94
  */
102
- export declare function useQuery<TFactory extends QueryFactory, const TThrow extends boolean | undefined = undefined>(factory: TFactory, handle: EnsuredQueryHandle<TFactory>, options?: UseQueryOptions & UseQueryThrowOptions<TFactory> & {
103
- readonly throwOnError?: TThrow;
104
- }): UseEnsuredQueryResult<TFactory, TThrow>;
105
95
  export declare function useQuery<TFactory extends QueryFactory, const TThrow extends boolean | undefined = undefined>(factory: TFactory, handle: QueryHandle<TFactory>, options?: UseQueryOptions & UseQueryThrowOptions<TFactory> & {
106
96
  readonly throwOnError?: TThrow;
107
97
  }): UseQueryResult<TFactory, TThrow>;
@@ -3,7 +3,7 @@ import { useQueryClient } from "./provider.mjs";
3
3
  import { assertSent } from "./browser-requests.mjs";
4
4
  import { Query, QueryObserver, fulfilled, pending } from "@raf-query/core";
5
5
  import { Effect, Result } from "effect";
6
- import { use, useEffect, useState, useSyncExternalStore } from "react";
6
+ import { useEffect, useState, useSyncExternalStore } from "react";
7
7
  //#region src/use-query.ts
8
8
  function queryFor(client, factory, input) {
9
9
  const args = [input];
@@ -87,12 +87,7 @@ function useQuery(factory, handle, options = {}) {
87
87
  ]);
88
88
  QueryObserver.trackProp(observer, "promise");
89
89
  const controls = withPromiseCommands(QueryObserver.trackResult(observer, result));
90
- if (!(options.throwOnError ?? client.throwOnError)) {
91
- const resultPromise = asResultThenable(result.promise);
92
- if (handle.ensured === true) return [use(resultPromise), controls];
93
- return [resultPromise, controls];
94
- }
95
- if (handle.ensured === true) return [use(result.promise), controls];
90
+ if (!(options.throwOnError ?? client.throwOnError)) return [asResultThenable(result.promise), controls];
96
91
  return [result.promise, controls];
97
92
  }
98
93
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/react",
3
- "version": "0.7.12",
3
+ "version": "0.8.0",
4
4
  "description": "React bindings for raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",
@@ -46,7 +46,7 @@
46
46
  }
47
47
  },
48
48
  "dependencies": {
49
- "@raf-query/core": "0.7.12"
49
+ "@raf-query/core": "0.8.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@tanstack/react-router": "^1.170.0",