@raf-query/react 0.7.11 → 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,14 +1,39 @@
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
+
17
+ ## [0.7.12](https://github.com/KATT/raf-query/compare/0.7.11...0.7.12) (2026-10-15)
18
+
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))
23
+
24
+ ### Features
25
+
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))
27
+
3
28
  ## [0.7.11](https://github.com/KATT/raf-query/compare/0.7.10...0.7.11) (2026-10-14)
4
29
 
5
30
  ### Features
6
31
 
7
- * **examples:** add a stale time setting ([#119](https://github.com/KATT/raf-query/issues/119)) ([02467ef](https://github.com/KATT/raf-query/commit/02467ef4cf700d2ca1a57647c2fbc5cad2bf7abc))
32
+ - **examples:** add a stale time setting ([#119](https://github.com/KATT/raf-query/issues/119)) ([02467ef](https://github.com/KATT/raf-query/commit/02467ef4cf700d2ca1a57647c2fbc5cad2bf7abc))
8
33
 
9
34
  ### Bug Fixes
10
35
 
11
- * **core:** leave error out of query types when it isn't inferred ([#120](https://github.com/KATT/raf-query/issues/120)) ([d2098e8](https://github.com/KATT/raf-query/commit/d2098e84dea31c8e0d136f7850177e37f56d4678)), references [#69](https://github.com/KATT/raf-query/issues/69) [#69](https://github.com/KATT/raf-query/issues/69)
36
+ - **core:** leave error out of query types when it isn't inferred ([#120](https://github.com/KATT/raf-query/issues/120)) ([d2098e8](https://github.com/KATT/raf-query/commit/d2098e84dea31c8e0d136f7850177e37f56d4678)), references [#69](https://github.com/KATT/raf-query/issues/69) [#69](https://github.com/KATT/raf-query/issues/69)
12
37
 
13
38
  ## [0.7.10](https://github.com/KATT/raf-query/compare/0.7.9...0.7.10) (2026-10-14)
14
39
 
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
 
@@ -35,4 +35,4 @@ function assertSent(client, query) {
35
35
  if (!state.hasData && !state.isFetching && state.status !== "error") throw new BrowserRenderError(query.hash);
36
36
  }
37
37
  //#endregion
38
- export { BrowserRenderError, assertSent, requestInBrowserOnly, startsRequests };
38
+ export { assertSent, requestInBrowserOnly, startsRequests };
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
@@ -101,4 +101,4 @@ function visibleRows(rows, filter, sortBy) {
101
101
  return rows.filter((row) => row.hash.toLowerCase().includes(needle)).toSorted(compareRows(sortBy));
102
102
  }
103
103
  //#endregion
104
- export { countByStatus, sortOrders, statusOf, statuses, useQueryRows, visibleRows };
104
+ export { countByStatus, sortOrders, statuses, useQueryRows, visibleRows };
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,5 +1,4 @@
1
- import "./client.mjs";
2
- import { DataOf, EnsuredQueryHandle, ErrorOf, InputOf, IsPaged, Query, QueryFactory, QueryHandle, QueryKey, QueryObserver } from "@raf-query/core";
1
+ import { DataOf, ErrorOf, InputOf, IsPaged, QueryFactory, QueryHandle, QueryKey, QueryObserver } from "@raf-query/core";
3
2
  import { Result } from "effect";
4
3
  //#region src/use-query.d.ts
5
4
  /** `refetchInterval`, `refetchOnWindowFocus`, `refetchOnReconnect`, `whilePending`. */
@@ -64,8 +63,6 @@ export type HasTypedError<TFactory extends QueryFactory> = unknown extends Error
64
63
  */
65
64
  export type ThrowsOnError<TFactory extends QueryFactory, TThrow extends boolean | undefined> = HasTypedError<TFactory> extends false ? true : TThrow extends boolean ? TThrow : false;
66
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>];
67
- /** {@link useQuery}'s result for a handle from `ensure`. */
68
- 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>];
69
66
  /**
70
67
  * Read the query a handle points at. Returns a promise to unwrap with
71
68
  * `use()` and the query's controls:
@@ -90,19 +87,11 @@ export type UseEnsuredQueryResult<TFactory extends QueryFactory, TThrow extends
90
87
  * The component re-renders when the promise changes, and when a control it
91
88
  * has read changes; changes to controls it never reads are skipped.
92
89
  *
93
- * A handle from `ensure` had its data loaded before the route rendered, so
94
- * the hook returns the data (or `Result`) itself:
95
- *
96
- * ```tsx
97
- * const [post, postState] = useQuery(postQuery, loaderData.post);
98
- * ```
99
- *
100
- * If that entry has lost its data since (garbage-collected, `reset`), the
101
- * 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`).
102
94
  */
103
- export declare function useQuery<TFactory extends QueryFactory, const TThrow extends boolean | undefined = undefined>(factory: TFactory, handle: EnsuredQueryHandle<TFactory>, options?: UseQueryOptions & UseQueryThrowOptions<TFactory> & {
104
- readonly throwOnError?: TThrow;
105
- }): UseEnsuredQueryResult<TFactory, TThrow>;
106
95
  export declare function useQuery<TFactory extends QueryFactory, const TThrow extends boolean | undefined = undefined>(factory: TFactory, handle: QueryHandle<TFactory>, options?: UseQueryOptions & UseQueryThrowOptions<TFactory> & {
107
96
  readonly throwOnError?: TThrow;
108
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,13 +87,8 @@ 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
99
- export { queryFor, useQuery };
94
+ export { useQuery };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/react",
3
- "version": "0.7.11",
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.11"
49
+ "@raf-query/core": "0.8.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "@tanstack/react-router": "^1.170.0",