@raf-query/react 0.1.6 → 0.1.8

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +57 -5
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,8 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.8](https://github.com/KATT/raf-query/compare/0.1.7...0.1.8) (2026-10-13)
4
+
5
+ ### Features
6
+
7
+ * **examples:** infinite scroll, root dev scripts, readable request names; README and tests cover pagination and infinite scroll ([#37](https://github.com/KATT/raf-query/issues/37)) ([2c3bed6](https://github.com/KATT/raf-query/commit/2c3bed630fd08d0a59686a6f5f14aecba1ff2e1b))
8
+
9
+ ## [0.1.7](https://github.com/KATT/raf-query/compare/0.1.6...0.1.7) (2026-10-13)
10
+
11
+ - validate search params with a zod schema in the README ([#36](https://github.com/KATT/raf-query/issues/36)) ([9142236](https://github.com/KATT/raf-query/commit/9142236f611deb0fdf9db5f7e2847bccad89e841))
12
+
3
13
  ## [0.1.6](https://github.com/KATT/raf-query/compare/0.1.5...0.1.6) (2026-10-12)
4
14
 
5
- * one file per decision, and alternatives in the PR template ([#34](https://github.com/KATT/raf-query/issues/34)) ([e60d30b](https://github.com/KATT/raf-query/commit/e60d30bc99452eec7178fa2a6c7598987fe5254c)), references [#24](https://github.com/KATT/raf-query/issues/24) [#25](https://github.com/KATT/raf-query/issues/25) [#26](https://github.com/KATT/raf-query/issues/26) [#27](https://github.com/KATT/raf-query/issues/27) [#28](https://github.com/KATT/raf-query/issues/28) [#33](https://github.com/KATT/raf-query/issues/33) [#26](https://github.com/KATT/raf-query/issues/26) [#N](https://github.com/KATT/raf-query/issues/N) [#26](https://github.com/KATT/raf-query/issues/26) [#16](https://github.com/KATT/raf-query/issues/16) [#23](https://github.com/KATT/raf-query/issues/23) [#31](https://github.com/KATT/raf-query/issues/31) [#19](https://github.com/KATT/raf-query/issues/19) [#28](https://github.com/KATT/raf-query/issues/28) [#33](https://github.com/KATT/raf-query/issues/33)
15
+ - one file per decision, and alternatives in the PR template ([#34](https://github.com/KATT/raf-query/issues/34)) ([e60d30b](https://github.com/KATT/raf-query/commit/e60d30bc99452eec7178fa2a6c7598987fe5254c)), references [#24](https://github.com/KATT/raf-query/issues/24) [#25](https://github.com/KATT/raf-query/issues/25) [#26](https://github.com/KATT/raf-query/issues/26) [#27](https://github.com/KATT/raf-query/issues/27) [#28](https://github.com/KATT/raf-query/issues/28) [#33](https://github.com/KATT/raf-query/issues/33) [#26](https://github.com/KATT/raf-query/issues/26) [#N](https://github.com/KATT/raf-query/issues/N) [#26](https://github.com/KATT/raf-query/issues/26) [#16](https://github.com/KATT/raf-query/issues/16) [#23](https://github.com/KATT/raf-query/issues/23) [#31](https://github.com/KATT/raf-query/issues/31) [#19](https://github.com/KATT/raf-query/issues/19) [#28](https://github.com/KATT/raf-query/issues/28) [#33](https://github.com/KATT/raf-query/issues/33)
6
16
 
7
17
  ## [0.1.5](https://github.com/KATT/raf-query/compare/0.1.4...0.1.5) (2026-10-12)
8
18
 
package/README.md CHANGED
@@ -273,18 +273,70 @@ Paging controls: `fetchNextPage()`, `fetchPreviousPage()`, `hasNextPage`, `hasPr
273
273
 
274
274
  On the server, `ensure` and `fetch` load the first page. Pass `{ pages: n }` as a third argument to load more up front; the option is only accepted for paged factories.
275
275
 
276
+ ### Infinite scroll
277
+
278
+ Infinite scroll is the same paged query with an automatic "Load more". A ref callback watches the button and presses it when it nears the viewport. Unmount the button while a page loads: it watches again when it remounts, so it keeps loading while it stays in reach. Its place is taken by skeletons the size of the incoming page, so the loaded rows replace them without moving anything below.
279
+
280
+ ```tsx
281
+ function Comments(props: { handle: QueryHandle<typeof commentsQuery> }) {
282
+ const [pagesPromise, comments] = useQuery(commentsQuery, props.handle);
283
+ const data = use(pagesPromise);
284
+
285
+ return (
286
+ <>
287
+ {data.pages
288
+ .flatMap((page) => page.items)
289
+ .map((comment) => (
290
+ <Comment key={comment.id} {...comment} />
291
+ ))}
292
+ {comments.isFetchingNextPage ? <CommentSkeletons /> : null}
293
+ {comments.hasNextPage && !comments.isFetchingNextPage ? (
294
+ <button
295
+ onClick={() => comments.fetchNextPage()}
296
+ ref={(button) => {
297
+ if (button === null) return;
298
+ const observer = new IntersectionObserver(
299
+ (entries) => {
300
+ if (entries.some((entry) => entry.isIntersecting)) {
301
+ observer.disconnect();
302
+ comments.fetchNextPage();
303
+ }
304
+ },
305
+ { rootMargin: "0px 0px 300px 0px" },
306
+ );
307
+ observer.observe(button);
308
+ return () => observer.disconnect();
309
+ }}
310
+ >
311
+ Load more
312
+ </button>
313
+ ) : null}
314
+ </>
315
+ );
316
+ }
317
+ ```
318
+
319
+ Pagination and infinite scroll differ in where the page lives:
320
+
321
+ - **Pagination**: the page is a search param and part of the input, so each page is its own query and the URL links to it ([below](#when-the-url-changes)).
322
+ - **Infinite scroll**: filters and sort are search params, and pages are loaded into one paged query per input. Changing a filter starts a new list from its first page.
323
+
324
+ The [examples](examples/) load their issue list and comments by infinite scroll.
325
+
276
326
  ### When the URL changes
277
327
 
278
328
  Filters, sort order, and pagination are search params. The loader turns them into the query's input, so every navigation starts the right query and the component only ever reads the handle it was given:
279
329
 
280
330
  ```tsx
281
- type PostsSearch = { sort: "newest" | "oldest"; page: number };
331
+ import { z } from "zod";
332
+
333
+ const PostsSearch = z.object({
334
+ sort: z.enum(["newest", "oldest"]).default("newest"),
335
+ page: z.int().positive().default(1),
336
+ });
282
337
 
283
338
  export const Route = createFileRoute("/posts")({
284
- validateSearch: (search): PostsSearch => ({
285
- sort: search.sort === "oldest" ? "oldest" : "newest",
286
- page: Number(search.page ?? 1),
287
- }),
339
+ validateSearch: PostsSearch,
288
340
  loaderDeps: (args) => args.search,
289
341
  loader: (args) => ({
290
342
  posts: args.context.queryClient.prefetch(postsQuery, args.deps),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/react",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "React bindings for raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",
@@ -40,7 +40,7 @@
40
40
  "./tanstack-router": "./dist/tanstack-router.mjs"
41
41
  },
42
42
  "dependencies": {
43
- "@raf-query/core": "0.1.6",
43
+ "@raf-query/core": "0.1.8",
44
44
  "effect": "^4.0.1"
45
45
  },
46
46
  "peerDependencies": {