@raf-query/react 0.12.0 → 0.13.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,42 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.0](https://github.com/KATT/raf-query/compare/0.12.0...0.13.0) (2026-11-10)
4
+
5
+ ### ⚠ BREAKING CHANGES
6
+
7
+ * **core:** paging lives in core; useInfiniteQuery reads core's PageControls ([#246](https://github.com/KATT/raf-query/issues/246))
8
+
9
+ ### Features
10
+
11
+ * **core:** paging lives in core; useInfiniteQuery reads core's PageControls ([#246](https://github.com/KATT/raf-query/issues/246)) ([f6b4ed2](https://github.com/KATT/raf-query/commit/f6b4ed210340b4b25bf3316ef08a9c8ceb9ed112))
12
+ * **core:** pass the client making the request to queryFn ([#241](https://github.com/KATT/raf-query/issues/241)) ([8c85746](https://github.com/KATT/raf-query/commit/8c85746c230bc3d8a426b32a130a260fa7e8ca62))
13
+ * **core:** replay cached entries to a new client subscriber ([#243](https://github.com/KATT/raf-query/issues/243)) ([1455eed](https://github.com/KATT/raf-query/commit/1455eed2612fe69f0f10bfec08cfd552ef90c786))
14
+ * **core:** ssr: false for queries only a browser can run ([#240](https://github.com/KATT/raf-query/issues/240)) ([077de62](https://github.com/KATT/raf-query/commit/077de6223a92b8bd8d35f7df043d1efe147ca403))
15
+
16
+ ### Bug Fixes
17
+
18
+ * **core:** infer factories built inline by a generic maker in setData ([#244](https://github.com/KATT/raf-query/issues/244)) ([da87c07](https://github.com/KATT/raf-query/commit/da87c07a3463a919c154ac3ac5fba3d546b3231e))
19
+ * **core:** keep data written while a request ran ([#239](https://github.com/KATT/raf-query/issues/239)) ([4cb7cc0](https://github.com/KATT/raf-query/commit/4cb7cc0605a2d4637591eb365153c5e955eb41a8))
20
+ * **core:** start features once for providers that share a client ([#242](https://github.com/KATT/raf-query/issues/242)) ([d5968fb](https://github.com/KATT/raf-query/commit/d5968fb140429a1b2e7fb94662c266a52e877cc0))
21
+
22
+ ### Documentation
23
+
24
+ * every example is the blog's posts, comments and authors ([#236](https://github.com/KATT/raf-query/issues/236)) ([2551e97](https://github.com/KATT/raf-query/commit/2551e9710aa7b149be333a1675dae31d9d1f5efd)), references [#230](https://github.com/KATT/raf-query/issues/230)
25
+
26
+ ### Miscellaneous Chores
27
+
28
+ * **lint:** require a docs link on every public export ([#237](https://github.com/KATT/raf-query/issues/237)) ([b5c8133](https://github.com/KATT/raf-query/commit/b5c8133c129e0412e82cd2f24da6a2516b4a2012))
29
+ * unblock CI: [@see](https://github.com/see) links and the RSC test's build ([#245](https://github.com/KATT/raf-query/issues/245)) ([84927e4](https://github.com/KATT/raf-query/commit/84927e4a900f7608e1e17b022e28afadbe00e4ae)), references [#243](https://github.com/KATT/raf-query/issues/243) [#246](https://github.com/KATT/raf-query/issues/246) [#240](https://github.com/KATT/raf-query/issues/240) [#238](https://github.com/KATT/raf-query/issues/238)
30
+
3
31
  ## [0.12.0](https://github.com/KATT/raf-query/compare/0.11.1...0.12.0) (2026-11-08)
4
32
 
5
33
  ### ⚠ BREAKING CHANGES
6
34
 
7
- * greenfield rewrite on a promise kernel, with load() handles and opt-in behaviors ([#230](https://github.com/KATT/raf-query/issues/230))
35
+ - greenfield rewrite on a promise kernel, with load() handles and opt-in behaviors ([#230](https://github.com/KATT/raf-query/issues/230))
8
36
 
9
37
  ### Features
10
38
 
11
- * greenfield rewrite on a promise kernel, with load() handles and opt-in behaviors ([#230](https://github.com/KATT/raf-query/issues/230)) ([e2a6f85](https://github.com/KATT/raf-query/commit/e2a6f85297992dc8a5cdd3f871a54452393ae978))
39
+ - greenfield rewrite on a promise kernel, with load() handles and opt-in behaviors ([#230](https://github.com/KATT/raf-query/issues/230)) ([e2a6f85](https://github.com/KATT/raf-query/commit/e2a6f85297992dc8a5cdd3f871a54452393ae978))
12
40
 
13
41
  ## [0.11.1](https://github.com/KATT/raf-query/compare/0.11.0...0.11.1) (2026-10-17)
14
42
 
package/dist/bind.d.mts CHANGED
@@ -14,6 +14,8 @@ import { RootOf } from "@raf-query/core/internal";
14
14
  * It returns `useQueryClient` itself; only the types change. It isn't a
15
15
  * hook, so call it at module level. This module has no `"use client"`, so a
16
16
  * server module can import the file that binds it.
17
+ *
18
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
17
19
  */
18
20
  export declare function bindUseQueryClient<T>(): () => QueryClient<RootOf<T>>;
19
21
  //#endregion
package/dist/bind.mjs CHANGED
@@ -13,6 +13,8 @@ import { useQueryClient } from "./provider.mjs";
13
13
  * It returns `useQueryClient` itself; only the types change. It isn't a
14
14
  * hook, so call it at module level. This module has no `"use client"`, so a
15
15
  * server module can import the file that binds it.
16
+ *
17
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
16
18
  */
17
19
  function bindUseQueryClient() {
18
20
  return useQueryClient;
@@ -1,6 +1,11 @@
1
1
  import { QueryClient } from "@raf-query/core";
2
2
  import { CSSProperties } from "react";
3
3
  //#region src/devtools.d.ts
4
+ /**
5
+ * Props of {@link QueryDevtoolsPanel}.
6
+ *
7
+ * @see https://raf-query.katt.dev/docs/devtools#props
8
+ */
4
9
  export interface QueryDevtoolsPanelProps {
5
10
  /** The client to inspect. Default: the nearest `QueryClientProvider`'s. */
6
11
  readonly client?: QueryClient;
@@ -9,6 +14,11 @@ export interface QueryDevtoolsPanelProps {
9
14
  /** Styles for the panel's root element, e.g. its height. */
10
15
  readonly style?: CSSProperties;
11
16
  }
17
+ /**
18
+ * Props of {@link QueryDevtools}.
19
+ *
20
+ * @see https://raf-query.katt.dev/docs/devtools
21
+ */
12
22
  export interface QueryDevtoolsProps {
13
23
  /** Corner of the toggle button. Default: `"bottom-right"`. */
14
24
  readonly buttonPosition?: "bottom-left" | "bottom-right" | "top-left" | "top-right";
@@ -17,8 +27,16 @@ export interface QueryDevtoolsProps {
17
27
  /** Open on the first render. */
18
28
  readonly initialIsOpen?: boolean;
19
29
  }
20
- /** The devtools panel, to place in your own layout. */
30
+ /**
31
+ * The devtools panel, to place in your own layout.
32
+ *
33
+ * @see https://raf-query.katt.dev/docs/devtools#embedding-the-panel
34
+ */
21
35
  export declare function QueryDevtoolsPanel(props: QueryDevtoolsPanelProps): import("react").JSX.Element;
22
- /** A toggle button that opens the devtools panel over the page. */
36
+ /**
37
+ * A toggle button that opens the devtools panel over the page.
38
+ *
39
+ * @see https://raf-query.katt.dev/docs/devtools
40
+ */
23
41
  export declare function QueryDevtools(props: QueryDevtoolsProps): import("react").JSX.Element;
24
42
  //#endregion
package/dist/devtools.mjs CHANGED
@@ -179,7 +179,11 @@ function Panel(props) {
179
179
  })]
180
180
  });
181
181
  }
182
- /** The devtools panel, to place in your own layout. */
182
+ /**
183
+ * The devtools panel, to place in your own layout.
184
+ *
185
+ * @see https://raf-query.katt.dev/docs/devtools#embedding-the-panel
186
+ */
183
187
  function QueryDevtoolsPanel(props) {
184
188
  const nearest = useOptionalQueryClient();
185
189
  const client = props.client ?? nearest;
@@ -207,7 +211,11 @@ const corners = {
207
211
  top: 12
208
212
  }
209
213
  };
210
- /** A toggle button that opens the devtools panel over the page. */
214
+ /**
215
+ * A toggle button that opens the devtools panel over the page.
216
+ *
217
+ * @see https://raf-query.katt.dev/docs/devtools
218
+ */
211
219
  function QueryDevtools(props) {
212
220
  const [open, setOpen] = useState(props.initialIsOpen ?? false);
213
221
  const corner = corners[props.buttonPosition ?? "bottom-right"];
@@ -10,6 +10,8 @@ import { HydrationBoundaryProps } from "./hydration-boundary.mjs";
10
10
  * It also marks the client components' server render: from there on, a read
11
11
  * of a query nothing sent renders its Suspense fallback on the server and
12
12
  * loads in the browser, instead of fetching where nothing would send it.
13
+ *
14
+ * @see https://raf-query.katt.dev/docs/react-server-components#setup
13
15
  */
14
16
  export declare function HydrationBoundary(props: HydrationBoundaryProps): import("react").JSX.Element;
15
17
  //#endregion
@@ -22,6 +22,8 @@ function sentHashes(client) {
22
22
  * It also marks the client components' server render: from there on, a read
23
23
  * of a query nothing sent renders its Suspense fallback on the server and
24
24
  * loads in the browser, instead of fetching where nothing would send it.
25
+ *
26
+ * @see https://raf-query.katt.dev/docs/react-server-components#setup
25
27
  */
26
28
  function HydrationBoundary(props) {
27
29
  const client = props.client;
@@ -1,6 +1,11 @@
1
1
  import { DehydrateOptions, DehydratedState, QueryClient } from "@raf-query/core";
2
2
  import { ReactNode } from "react";
3
3
  //#region src/hydration-boundary/hydration-boundary.d.ts
4
+ /**
5
+ * Props of {@link HydrationBoundary}: a dehydrated `state`, or in server components the request's `client`.
6
+ *
7
+ * @see https://raf-query.katt.dev/docs/react-router#server-loaders
8
+ */
4
9
  export type HydrationBoundaryProps = {
5
10
  readonly children?: ReactNode;
6
11
  /**
@@ -39,6 +44,8 @@ export type HydrationBoundaryProps = {
39
44
  * With loaders, such as React Router Framework Mode, pass the `state` the
40
45
  * loader dehydrated. Pending entries cross as promises when the framework's
41
46
  * serializer supports them (React Router's Single Fetch does).
47
+ *
48
+ * @see https://raf-query.katt.dev/docs/react-router#server-loaders
42
49
  */
43
50
  export declare function HydrationBoundary(props: HydrationBoundaryProps): import("react").JSX.Element;
44
51
  //#endregion
@@ -24,6 +24,8 @@ import { jsx } from "react/jsx-runtime";
24
24
  * With loaders, such as React Router Framework Mode, pass the `state` the
25
25
  * loader dehydrated. Pending entries cross as promises when the framework's
26
26
  * serializer supports them (React Router's Single Fetch does).
27
+ *
28
+ * @see https://raf-query.katt.dev/docs/react-router#server-loaders
27
29
  */
28
30
  function HydrationBoundary(props) {
29
31
  if (props.state === void 0) throw new Error("HydrationBoundary needs `state` here. `client` works only in server components.");
@@ -1,10 +1,10 @@
1
1
  import { QueryDevtools, QueryDevtoolsPanel, QueryDevtoolsPanelProps, QueryDevtoolsProps } from "./devtools.mjs";
2
2
  import { QueryClientProvider } from "./provider.mjs";
3
3
  import { QueryState, QueryValue, UseQueryOptions } from "./use-query.mjs";
4
- import { InfiniteQueryState, PageControls } from "./use-infinite-query.mjs";
4
+ import { InfiniteQueryState } from "./use-infinite-query.mjs";
5
5
  import "./index-shared.mjs";
6
6
  import { HydrationBoundaryProps } from "./hydration-boundary/hydration-boundary.mjs";
7
7
  import { HydrationBoundary } from "./hydration-boundary/hydration-boundary-react-server.mjs";
8
8
  import { bindUseQueryClient, useInfiniteQuery, useIsFetching, useQuery, useQueryClient } from "./react-server-hooks.mjs";
9
9
  export * from "@raf-query/core";
10
- export { HydrationBoundary, type HydrationBoundaryProps, type InfiniteQueryState, type PageControls, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions, bindUseQueryClient, useInfiniteQuery, useIsFetching, useQuery, useQueryClient };
10
+ export { HydrationBoundary, type HydrationBoundaryProps, type InfiniteQueryState, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions, bindUseQueryClient, useInfiniteQuery, useIsFetching, useQuery, useQueryClient };
@@ -1,6 +1,6 @@
1
1
  import { QueryDevtools, QueryDevtoolsPanel, QueryDevtoolsPanelProps, QueryDevtoolsProps } from "./devtools.mjs";
2
2
  import { QueryClientProvider } from "./provider.mjs";
3
3
  import { QueryState, QueryValue, UseQueryOptions } from "./use-query.mjs";
4
- import { InfiniteQueryState, PageControls } from "./use-infinite-query.mjs";
4
+ import { InfiniteQueryState } from "./use-infinite-query.mjs";
5
5
  export * from "@raf-query/core";
6
- export { type InfiniteQueryState, type PageControls, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions };
6
+ export { type InfiniteQueryState, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { QueryDevtools, QueryDevtoolsPanel, QueryDevtoolsPanelProps, QueryDevtoolsProps } from "./devtools.mjs";
2
2
  import { QueryClientProvider, useQueryClient } from "./provider.mjs";
3
3
  import { QueryState, QueryValue, UseQueryOptions, useQuery } from "./use-query.mjs";
4
- import { InfiniteQueryState, PageControls, useInfiniteQuery } from "./use-infinite-query.mjs";
4
+ import { InfiniteQueryState, useInfiniteQuery } from "./use-infinite-query.mjs";
5
5
  import "./index-shared.mjs";
6
6
  import { HydrationBoundary, HydrationBoundaryProps } from "./hydration-boundary/hydration-boundary.mjs";
7
7
  import { useIsFetching } from "./use-is-fetching.mjs";
8
8
  import { bindUseQueryClient } from "./bind.mjs";
9
9
  export * from "@raf-query/core";
10
- export { HydrationBoundary, type HydrationBoundaryProps, type InfiniteQueryState, type PageControls, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions, bindUseQueryClient, useInfiniteQuery, useIsFetching, useQuery, useQueryClient };
10
+ export { HydrationBoundary, type HydrationBoundaryProps, type InfiniteQueryState, QueryClientProvider, QueryDevtools, QueryDevtoolsPanel, type QueryDevtoolsPanelProps, type QueryDevtoolsProps, type QueryState, type QueryValue, type UseQueryOptions, bindUseQueryClient, useInfiniteQuery, useIsFetching, useQuery, useQueryClient };
@@ -4,11 +4,17 @@ import { ReactNode } from "react";
4
4
  /**
5
5
  * Provides a client to the tree, and runs its features (focus and
6
6
  * reconnect refetching, polling, …) while mounted.
7
+ *
8
+ * @see https://raf-query.katt.dev/docs/ssr-and-hydration#the-provider
7
9
  */
8
10
  export declare function QueryClientProvider(props: {
9
11
  readonly children?: ReactNode;
10
12
  readonly client: QueryClient;
11
13
  }): import("react").JSX.Element;
12
- /** The client from the nearest {@link QueryClientProvider}. */
14
+ /**
15
+ * The client from the nearest {@link QueryClientProvider}.
16
+ *
17
+ * @see https://raf-query.katt.dev/docs/api-reference#providers
18
+ */
13
19
  export declare function useQueryClient(): QueryClient;
14
20
  //#endregion
package/dist/provider.mjs CHANGED
@@ -7,6 +7,8 @@ const QueryClientContext = createContext(null);
7
7
  /**
8
8
  * Provides a client to the tree, and runs its features (focus and
9
9
  * reconnect refetching, polling, …) while mounted.
10
+ *
11
+ * @see https://raf-query.katt.dev/docs/ssr-and-hydration#the-provider
10
12
  */
11
13
  function QueryClientProvider(props) {
12
14
  const client = props.client;
@@ -20,7 +22,11 @@ function QueryClientProvider(props) {
20
22
  function useOptionalQueryClient() {
21
23
  return use(QueryClientContext);
22
24
  }
23
- /** The client from the nearest {@link QueryClientProvider}. */
25
+ /**
26
+ * The client from the nearest {@link QueryClientProvider}.
27
+ *
28
+ * @see https://raf-query.katt.dev/docs/api-reference#providers
29
+ */
24
30
  function useQueryClient() {
25
31
  const client = useOptionalQueryClient();
26
32
  if (!client) throw new Error("useQueryClient: no QueryClientProvider above this component");
@@ -5,13 +5,39 @@ import { useIsFetching as useIsFetching$1 } from "./use-is-fetching.mjs";
5
5
  import { QueryClient } from "@raf-query/core";
6
6
  import { RootOf } from "@raf-query/core/internal";
7
7
  //#region src/react-server-hooks.d.ts
8
+ /**
9
+ * `useQuery` in a server component: throws, since hooks belong in client
10
+ * components.
11
+ *
12
+ * @see https://raf-query.katt.dev/docs/react-server-components
13
+ */
8
14
  export declare const useQuery: typeof useQuery$1;
15
+ /**
16
+ * `useInfiniteQuery` in a server component: throws, since hooks belong in client
17
+ * components.
18
+ *
19
+ * @see https://raf-query.katt.dev/docs/react-server-components
20
+ */
9
21
  export declare const useInfiniteQuery: typeof useInfiniteQuery$1;
22
+ /**
23
+ * `useIsFetching` in a server component: throws, since hooks belong in client
24
+ * components.
25
+ *
26
+ * @see https://raf-query.katt.dev/docs/react-server-components
27
+ */
10
28
  export declare const useIsFetching: typeof useIsFetching$1;
29
+ /**
30
+ * `useQueryClient` in a server component: throws, since hooks belong in client
31
+ * components.
32
+ *
33
+ * @see https://raf-query.katt.dev/docs/react-server-components
34
+ */
11
35
  export declare const useQueryClient: typeof useQueryClient$1;
12
36
  /**
13
37
  * `bindUseQueryClient` runs at module level in a file server modules may
14
38
  * import too, so it works here and returns the throwing `useQueryClient`.
39
+ *
40
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
15
41
  */
16
42
  export declare function bindUseQueryClient<T>(): () => QueryClient<RootOf<T>>;
17
43
  //#endregion
@@ -4,13 +4,39 @@ function clientOnly(name) {
4
4
  throw new Error(`${name} reads in client components: move this into a file with "use client". Server components start queries with load() and send them with <HydrationBoundary>.`);
5
5
  };
6
6
  }
7
+ /**
8
+ * `useQuery` in a server component: throws, since hooks belong in client
9
+ * components.
10
+ *
11
+ * @see https://raf-query.katt.dev/docs/react-server-components
12
+ */
7
13
  const useQuery = /* @__PURE__ */ clientOnly("useQuery");
14
+ /**
15
+ * `useInfiniteQuery` in a server component: throws, since hooks belong in client
16
+ * components.
17
+ *
18
+ * @see https://raf-query.katt.dev/docs/react-server-components
19
+ */
8
20
  const useInfiniteQuery = /* @__PURE__ */ clientOnly("useInfiniteQuery");
21
+ /**
22
+ * `useIsFetching` in a server component: throws, since hooks belong in client
23
+ * components.
24
+ *
25
+ * @see https://raf-query.katt.dev/docs/react-server-components
26
+ */
9
27
  const useIsFetching = /* @__PURE__ */ clientOnly("useIsFetching");
28
+ /**
29
+ * `useQueryClient` in a server component: throws, since hooks belong in client
30
+ * components.
31
+ *
32
+ * @see https://raf-query.katt.dev/docs/react-server-components
33
+ */
10
34
  const useQueryClient = /* @__PURE__ */ clientOnly("useQueryClient");
11
35
  /**
12
36
  * `bindUseQueryClient` runs at module level in a file server modules may
13
37
  * import too, so it works here and returns the throwing `useQueryClient`.
38
+ *
39
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
14
40
  */
15
41
  function bindUseQueryClient() {
16
42
  return useQueryClient;
@@ -5,6 +5,8 @@ import { AnyRouter } from "@tanstack/react-router";
5
5
  * The browser build of `@raf-query/react/tanstack-router` (the `browser`
6
6
  * export condition): the client half only, so the server's dehydration
7
7
  * stream stays out of the app bundle.
8
+ *
9
+ * @see https://raf-query.katt.dev/docs/tanstack-start#setup
8
10
  */
9
11
  export declare function setupRouterIntegration<TRouter extends AnyRouter>(options: RouterIntegrationOptions<TRouter>): void;
10
12
  //#endregion
@@ -4,6 +4,8 @@ import { handleRedirects, setupClient } from "./tanstack-router-shared.mjs";
4
4
  * The browser build of `@raf-query/react/tanstack-router` (the `browser`
5
5
  * export condition): the client half only, so the server's dehydration
6
6
  * stream stays out of the app bundle.
7
+ *
8
+ * @see https://raf-query.katt.dev/docs/tanstack-start#setup
7
9
  */
8
10
  function setupRouterIntegration(options) {
9
11
  setupClient(options);
@@ -11,6 +11,11 @@ declare module "@tanstack/react-router" {
11
11
  rafQueryHandle: QueryHandle;
12
12
  }
13
13
  }
14
+ /**
15
+ * Options for `setupRouterIntegration`.
16
+ *
17
+ * @see https://raf-query.katt.dev/docs/tanstack-start#setup
18
+ */
14
19
  export interface RouterIntegrationOptions<TRouter extends AnyRouter> {
15
20
  readonly dehydrateOptions?: DehydrateOptions;
16
21
  /** Navigate when a `queryFn` throws `redirect()`. Default `true`. */
@@ -11,6 +11,8 @@ import { AnyRouter } from "@tanstack/react-router";
11
11
  * - Turns `redirect()` thrown from a `queryFn` into a navigation.
12
12
  *
13
13
  * Call it in `getRouter`, which runs once per request on the server.
14
+ *
15
+ * @see https://raf-query.katt.dev/docs/tanstack-start#setup
14
16
  */
15
17
  export declare function setupRouterIntegration<TRouter extends AnyRouter>(options: RouterIntegrationOptions<TRouter>): void;
16
18
  //#endregion
@@ -45,6 +45,8 @@ function setupServer(options) {
45
45
  * - Turns `redirect()` thrown from a `queryFn` into a navigation.
46
46
  *
47
47
  * Call it in `getRouter`, which runs once per request on the server.
48
+ *
49
+ * @see https://raf-query.katt.dev/docs/tanstack-start#setup
48
50
  */
49
51
  function setupRouterIntegration(options) {
50
52
  if (options.router.isServer) setupServer(options);
@@ -1,18 +1,12 @@
1
1
  import { QueryState, QueryValue, UseQueryOptions } from "./use-query.mjs";
2
- import { InfiniteQueryFactory, QueryHandle } from "@raf-query/core";
2
+ import { InfiniteQueryFactory, PageControls, QueryHandle } from "@raf-query/core";
3
3
  //#region src/use-infinite-query.d.ts
4
- /** The paging half of what `useInfiniteQuery` returns. */
5
- export interface PageControls {
6
- /** Load the page after the last one. Resolves when it's there. */
7
- fetchNextPage(): Promise<void>;
8
- /** Load the page before the first one. Resolves when it's there. */
9
- fetchPreviousPage(): Promise<void>;
10
- readonly hasNextPage: boolean;
11
- readonly hasPreviousPage: boolean;
12
- readonly isFetchingNextPage: boolean;
13
- readonly isFetchingPreviousPage: boolean;
14
- }
15
- /** What `useInfiniteQuery` returns next to the data. */
4
+ /**
5
+ * What `useInfiniteQuery` returns next to the data: core's paging controls
6
+ * and the query's state.
7
+ *
8
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
9
+ */
16
10
  export interface InfiniteQueryState<TFactory extends InfiniteQueryFactory = InfiniteQueryFactory> extends PageControls, QueryState<TFactory> {}
17
11
  /**
18
12
  * Read a paged query (`infiniteQueryOptions`) by its handle. The data is
@@ -22,6 +16,8 @@ export interface InfiniteQueryState<TFactory extends InfiniteQueryFactory = Infi
22
16
  * const [pagesThenable, pagesState] = useInfiniteQuery(commentsQuery, handles.comments);
23
17
  * const pages = use(pagesThenable);
24
18
  * ```
19
+ *
20
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
25
21
  */
26
22
  export declare function useInfiniteQuery<TFactory extends InfiniteQueryFactory>(factory: TFactory, handle: QueryHandle<TFactory>, options?: UseQueryOptions): readonly [QueryValue<TFactory>, InfiniteQueryState<TFactory>];
27
23
  //#endregion
@@ -1,21 +1,14 @@
1
- import { settled, useQueryRead } from "./use-query.mjs";
2
- import { fetchEntry, pageParamAfter } from "@raf-query/core/internal";
1
+ import { useQueryRead } from "./use-query.mjs";
2
+ import { fetchPage, pageState } from "@raf-query/core/internal";
3
3
  //#region src/use-infinite-query.ts
4
- function hasPage(entry, state, direction) {
5
- return state.hasData && pageParamAfter(entry.options, state.data, direction) !== void 0;
6
- }
4
+ /** Core's paging controls, split into stable actions and tracked fields. */
7
5
  function pageFields(entry, state) {
8
6
  return {
9
7
  actions: {
10
- fetchNextPage: () => settled(fetchEntry(entry, { direction: "next" })),
11
- fetchPreviousPage: () => settled(fetchEntry(entry, { direction: "previous" }))
8
+ fetchNextPage: () => fetchPage(entry, "next"),
9
+ fetchPreviousPage: () => fetchPage(entry, "previous")
12
10
  },
13
- fields: {
14
- hasNextPage: hasPage(entry, state, "next"),
15
- hasPreviousPage: hasPage(entry, state, "previous"),
16
- isFetchingNextPage: state.fetchingDirection === "next",
17
- isFetchingPreviousPage: state.fetchingDirection === "previous"
18
- }
11
+ fields: { ...pageState(entry, state) }
19
12
  };
20
13
  }
21
14
  /**
@@ -26,6 +19,8 @@ function pageFields(entry, state) {
26
19
  * const [pagesThenable, pagesState] = useInfiniteQuery(commentsQuery, handles.comments);
27
20
  * const pages = use(pagesThenable);
28
21
  * ```
22
+ *
23
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
29
24
  */
30
25
  function useInfiniteQuery(factory, handle, options) {
31
26
  const read = useQueryRead(factory, handle, options, pageFields);
@@ -5,6 +5,8 @@ import { AnyFactory, AnyTarget } from "@raf-query/core/internal";
5
5
  * How many queries have a request in flight: all of them, or a factory's,
6
6
  * a group's or a target's. For a global loading indicator. Always `0` on
7
7
  * the server and while hydrating, so the HTML matches the first browser render.
8
+ *
9
+ * @see https://raf-query.katt.dev/docs/background-fetching-indicators#useisfetching
8
10
  */
9
11
  export declare function useIsFetching(target?: AnyFactory | AnyTarget | Group): number;
10
12
  //#endregion
@@ -7,6 +7,8 @@ const serverCount = () => 0;
7
7
  * How many queries have a request in flight: all of them, or a factory's,
8
8
  * a group's or a target's. For a global loading indicator. Always `0` on
9
9
  * the server and while hydrating, so the HTML matches the first browser render.
10
+ *
11
+ * @see https://raf-query.katt.dev/docs/background-fetching-indicators#useisfetching
10
12
  */
11
13
  function useIsFetching(target) {
12
14
  const client = useQueryClient();
@@ -2,6 +2,11 @@ import "./tracked.mjs";
2
2
  import { DataOf, InputOf, QueryFactory, QueryHandle, SingleQueryFactory, Thenable } from "@raf-query/core";
3
3
  import "@raf-query/core/internal";
4
4
  //#region src/use-query.d.ts
5
+ /**
6
+ * Options for `useQuery` and `useInfiniteQuery`.
7
+ *
8
+ * @see https://raf-query.katt.dev/docs/url-state-and-pagination#what-shows-while-the-new-input-loads
9
+ */
5
10
  export interface UseQueryOptions {
6
11
  /**
7
12
  * While a new handle's query has no data: `"suspend"` (the default) shows
@@ -10,7 +15,11 @@ export interface UseQueryOptions {
10
15
  */
11
16
  readonly whilePending?: "previous" | "suspend";
12
17
  }
13
- /** What `useQuery` returns next to the data. */
18
+ /**
19
+ * What `useQuery` returns next to the data.
20
+ *
21
+ * @see https://raf-query.katt.dev/docs/reading-queries#state
22
+ */
14
23
  export interface QueryState<TFactory extends QueryFactory = QueryFactory> {
15
24
  /** The last request's error while it's the latest outcome. */
16
25
  readonly error: unknown;
@@ -33,19 +42,23 @@ export interface QueryState<TFactory extends QueryFactory = QueryFactory> {
33
42
  * to pass to `use()`.
34
43
  * A loader can't promise the data is still cached when a component renders
35
44
  * (a write can reset or remove it), so the read may suspend.
45
+ *
46
+ * @see https://raf-query.katt.dev/docs/reading-queries
36
47
  */
37
48
  export type QueryValue<TFactory extends QueryFactory> = Thenable<DataOf<TFactory>>;
38
49
  /**
39
50
  * Read a query by its handle.
40
51
  *
41
52
  * ```tsx
42
- * const [issueThenable, issueState] = useQuery(issueQuery, handles.issue);
43
- * const issue = use(issueThenable);
53
+ * const [postThenable, postState] = useQuery(postQuery, handles.post);
54
+ * const post = use(postThenable);
44
55
  * ```
45
56
  *
46
57
  * Reading never refetches stale data: loaders decide freshness. A query no
47
58
  * loader started fetches while rendering, which is a waterfall (see
48
59
  * `waterfallHandle`). Paged queries read with `useInfiniteQuery`.
60
+ *
61
+ * @see https://raf-query.katt.dev/docs/reading-queries
49
62
  */
50
63
  export declare function useQuery<TFactory extends SingleQueryFactory>(factory: TFactory, handle: QueryHandle<TFactory>, options?: UseQueryOptions): readonly [QueryValue<TFactory>, QueryState<TFactory>];
51
64
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { useQueryClient } from "./provider.mjs";
2
2
  import { browserRender, leavesUnstartedToBrowser } from "./browser-render.mjs";
3
3
  import { createTracker, renderedChanged, trackedState } from "./tracked.mjs";
4
- import { entryOf, fetchEntry, isInvalidated, isStale, isWaterfallHandle, mapThenable, subscribeEntry } from "@raf-query/core/internal";
4
+ import { entryOf, fetchEntry, isBrowserOnly, isInvalidated, isStale, isWaterfallHandle, mapThenable, subscribeEntry } from "@raf-query/core/internal";
5
5
  import { useCallback, useState, useSyncExternalStore } from "react";
6
6
  //#region src/use-query.ts
7
7
  /** Whether nothing is loading the entry: no data, no error, no request in flight. */
@@ -13,19 +13,27 @@ function isIdle(entry, state) {
13
13
  * waterfall handle, or of a query the cache dropped. A server render fed by
14
14
  * server components leaves it to the browser: nothing would send its data.
15
15
  */
16
+ /**
17
+ * Whether a server render leaves this idle entry to the browser: on a client
18
+ * fed by server components, or a query only the browser runs (`ssr: false`).
19
+ */
20
+ function leftToBrowser(entry) {
21
+ return leavesUnstartedToBrowser(entry.client) || isBrowserOnly(entry);
22
+ }
16
23
  function startIfMissing(entry, state, waterfall) {
17
24
  const client = entry.client;
18
- if (!isIdle(entry, state) || leavesUnstartedToBrowser(client)) return;
19
- if (process.env.NODE_ENV !== "production" && !waterfall && !client.isServer) console.warn(`raf-query: ${entry.hash} was read before anything loaded it, so it fetches while rendering. Start it in a loader with load(), or build the handle with waterfallHandle() to make the waterfall explicit.`);
25
+ if (!isIdle(entry, state) || leftToBrowser(entry)) return;
26
+ const expected = waterfall || entry.options?.ssr === false;
27
+ if (process.env.NODE_ENV !== "production" && !expected && !client.isServer) console.warn(`raf-query: ${entry.hash} was read before anything loaded it, so it fetches while rendering. Start it in a loader with load(), or build the handle with waterfallHandle() to make the waterfall explicit.`);
20
28
  fetchEntry(entry);
21
29
  }
22
30
  /**
23
- * In a server render fed by server components, an entry `startIfMissing`
24
- * left to the browser reads as a rejection: a `use()` of it inside Suspense
25
- * renders that boundary's fallback, and the browser renders the content.
31
+ * In a server render, an entry `startIfMissing` left to the browser reads as
32
+ * a rejection: a `use()` of it inside Suspense renders that boundary's
33
+ * fallback, and the browser renders the content.
26
34
  */
27
35
  function readOf(entry, state) {
28
- return leavesUnstartedToBrowser(entry.client) && isIdle(entry, state) ? browserRender(entry) : entry.thenable;
36
+ return leftToBrowser(entry) && isIdle(entry, state) ? browserRender(entry) : entry.thenable;
29
37
  }
30
38
  function settled(promise) {
31
39
  return promise.then(() => {});
@@ -95,17 +103,19 @@ function useQueryRead(factory, handle, options, extra) {
95
103
  * Read a query by its handle.
96
104
  *
97
105
  * ```tsx
98
- * const [issueThenable, issueState] = useQuery(issueQuery, handles.issue);
99
- * const issue = use(issueThenable);
106
+ * const [postThenable, postState] = useQuery(postQuery, handles.post);
107
+ * const post = use(postThenable);
100
108
  * ```
101
109
  *
102
110
  * Reading never refetches stale data: loaders decide freshness. A query no
103
111
  * loader started fetches while rendering, which is a waterfall (see
104
112
  * `waterfallHandle`). Paged queries read with `useInfiniteQuery`.
113
+ *
114
+ * @see https://raf-query.katt.dev/docs/reading-queries
105
115
  */
106
116
  function useQuery(factory, handle, options) {
107
117
  const read = useQueryRead(factory, handle, options);
108
118
  return [read.thenable, read.controls];
109
119
  }
110
120
  //#endregion
111
- export { settled, useQuery, useQueryRead };
121
+ export { useQuery, useQueryRead };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/react",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "React bindings for raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",
@@ -47,7 +47,7 @@
47
47
  }
48
48
  },
49
49
  "dependencies": {
50
- "@raf-query/core": "0.12.0"
50
+ "@raf-query/core": "0.13.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@tanstack/react-router": "^1.170.0",