Skip to content

Commit 083b7d0

Browse files
attempt repro
1 parent e474f73 commit 083b7d0

File tree

6 files changed

+231
-7
lines changed

6 files changed

+231
-7
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
3+
import { makeQueryClient } from "../make-query-client";
4+
import { getApiV1AuthorsOptions } from "../query";
5+
import { Authors } from "../client-component";
6+
7+
export default async function Page() {
8+
const queryClient = makeQueryClient()
9+
10+
const data = await queryClient.fetchQuery({...getApiV1AuthorsOptions()})
11+
12+
13+
return (
14+
<HydrationBoundary state={dehydrate(queryClient)}>
15+
<Authors />
16+
</HydrationBoundary>
17+
)
18+
}

integrations/react-next-15/app/client-component.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
'use client'
2-
2+
import { useQuery, useSuspenseQuery } from "@tanstack/react-query"
3+
import Link from "next/link"
34
import React from 'react'
4-
import { useQuery } from '@tanstack/react-query'
55
import { Temporal } from '@js-temporal/polyfill'
6+
import { getApiV1ActivitiesOptions, getApiV1AuthorsOptions } from './query'
67

78
export function ClientComponent() {
89
const query = useQuery({
@@ -34,3 +35,33 @@ export function ClientComponent() {
3435
</div>
3536
)
3637
}
38+
39+
40+
41+
42+
43+
export const Activities = () => {
44+
const { data: activities } = useSuspenseQuery({
45+
...getApiV1ActivitiesOptions(),
46+
})
47+
48+
return (
49+
<div className="grid gap-8">
50+
<Link href="/authors">Authors</Link>
51+
<pre>{JSON.stringify(activities, null, 2)}</pre>
52+
</div>
53+
)
54+
}
55+
56+
export const Authors = () => {
57+
const { data: authors } = useSuspenseQuery({
58+
...getApiV1AuthorsOptions(),
59+
})
60+
61+
return (
62+
<div className="grid gap-8">
63+
<Link href="/">Activities</Link>
64+
<pre>{JSON.stringify(authors, null, 2)}</pre>
65+
</div>
66+
)
67+
}

integrations/react-next-15/app/page.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { headers } from 'next/headers'
2-
import React from 'react'
2+
import React, { Suspense } from 'react'
33
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
44
import { Temporal } from '@js-temporal/polyfill'
5-
import { ClientComponent } from './client-component'
5+
import { Activities, ClientComponent } from './client-component'
66
import { makeQueryClient } from './make-query-client'
77
import { queryExampleAction } from './_action'
8+
import { getApiV1ActivitiesOptions } from './query'
89

910
export default function Home() {
1011
const queryClient = makeQueryClient()
@@ -26,16 +27,24 @@ export default function Home() {
2627
},
2728
})
2829

30+
31+
void queryClient.prefetchQuery({ ...getApiV1ActivitiesOptions() })
32+
33+
2934
const state = dehydrate(queryClient)
3035

3136
return (
3237
<main>
3338
<HydrationBoundary state={state}>
3439
<ClientComponent />
40+
<form action={queryExampleAction}>
41+
<button type="submit">Increment</button>
42+
</form>
43+
<Suspense fallback={<div>Loading activities...</div>}>
44+
<Activities />
45+
</Suspense>
3546
</HydrationBoundary>
36-
<form action={queryExampleAction}>
37-
<button type="submit">Increment</button>
38-
</form>
47+
3948
</main>
4049
)
4150
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { createClient, createConfig } from "@hey-api/client-next";
2+
import { queryOptions } from "@tanstack/react-query";
3+
4+
import type { Client, ClientOptions, CreateClientConfig, Options as HeyApiOptions, TDataShape } from "@hey-api/client-next";
5+
6+
export type Options<TData extends TDataShape = TDataShape, TThrowOnError extends boolean = boolean> = HeyApiOptions<TData, TThrowOnError> & {
7+
/**
8+
* You can provide a client instance returned by `createClient()` instead of
9+
* individual options. This might be also useful if you want to implement a
10+
* custom client.
11+
*/
12+
client?: Client;
13+
/**
14+
* You can pass arbitrary values through the `meta` object. This can be
15+
* used to access values that aren't defined as part of the SDK function.
16+
*/
17+
meta?: Record<string, unknown>;
18+
};
19+
20+
21+
export const createClientConfig: CreateClientConfig = (config) => ({
22+
...config,
23+
baseUrl: 'https://fakerestapi.azurewebsites.net/',
24+
})
25+
26+
27+
export const _heyApiClient = createClient(createClientConfig(createConfig<ClientOptions>({
28+
baseUrl: 'https://fakerestapi.azurewebsites.net'
29+
})));
30+
31+
export type GetApiV1ActivitiesData = {
32+
body?: never;
33+
path?: never;
34+
query?: never;
35+
url: '/api/v1/Activities';
36+
};
37+
38+
export type Activity = {
39+
id?: number;
40+
title?: string | null;
41+
dueDate?: string;
42+
completed?: boolean;
43+
};
44+
45+
export type Author = {
46+
id?: number;
47+
idBook?: number;
48+
firstName?: string | null;
49+
lastName?: string | null;
50+
};
51+
52+
export type GetApiV1ActivitiesResponses = {
53+
/**
54+
* Success
55+
*/
56+
200: Array<Activity>;
57+
};
58+
59+
export type GetApiV1AuthorsData = {
60+
body?: never;
61+
path?: never;
62+
query?: never;
63+
url: '/api/v1/Authors';
64+
};
65+
66+
export type GetApiV1ActivitiesResponse = GetApiV1ActivitiesResponses[keyof GetApiV1ActivitiesResponses];
67+
68+
export type QueryKey<TOptions extends Options> = [
69+
Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & {
70+
_id: string;
71+
_infinite?: boolean;
72+
}
73+
];
74+
75+
76+
const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean): [
77+
QueryKey<TOptions>[0]
78+
] => {
79+
const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: (options?.client ?? _heyApiClient).getConfig().baseUrl } as QueryKey<TOptions>[0];
80+
if (infinite) {
81+
params._infinite = infinite;
82+
}
83+
if (options?.body) {
84+
params.body = options.body;
85+
}
86+
if (options?.headers) {
87+
params.headers = options.headers;
88+
}
89+
if (options?.path) {
90+
params.path = options.path;
91+
}
92+
if (options?.query) {
93+
params.query = options.query;
94+
}
95+
return [
96+
params
97+
];
98+
};
99+
100+
export const getApiV1Activities = <TThrowOnError extends boolean = false>(options?: Options<GetApiV1ActivitiesData,TThrowOnError>) => {
101+
return (options?.client ?? _heyApiClient).get<GetApiV1ActivitiesResponse, unknown, TThrowOnError>({
102+
url: '/api/v1/Activities',
103+
...options
104+
});
105+
};
106+
107+
export const getApiV1ActivitiesQueryKey = (options?: Options<GetApiV1ActivitiesData>) => createQueryKey('getApiV1Activities', options);
108+
109+
110+
export const getApiV1ActivitiesOptions = (options?: Options<GetApiV1ActivitiesData>) => {
111+
return queryOptions({
112+
queryFn: async ({ queryKey, signal }) => {
113+
const { data } = await getApiV1Activities({
114+
...options,
115+
...queryKey[0],
116+
signal,
117+
throwOnError: true
118+
});
119+
return data;
120+
},
121+
queryKey: getApiV1ActivitiesQueryKey(options)
122+
});
123+
};
124+
125+
export type GetApiV1AuthorsResponses = {
126+
/**
127+
* Success
128+
*/
129+
200: Array<Author>;
130+
};
131+
132+
export type GetApiV1AuthorsResponse = GetApiV1AuthorsResponses[keyof GetApiV1AuthorsResponses];
133+
134+
135+
export const getApiV1Authors = <TThrowOnError extends boolean = false>(options?: Options<GetApiV1AuthorsData,TThrowOnError>) => {
136+
return (options?.client ?? _heyApiClient).get<GetApiV1AuthorsResponse, unknown, TThrowOnError>({
137+
url: '/api/v1/Authors',
138+
...options
139+
});
140+
};
141+
142+
export const getApiV1AuthorsQueryKey = (options?: Options<GetApiV1AuthorsData>) => createQueryKey('getApiV1Authors', options);
143+
144+
export const getApiV1AuthorsOptions = (options?: Options<GetApiV1AuthorsData>) => {
145+
return queryOptions({
146+
queryFn: async ({ queryKey, signal }) => {
147+
const { data } = await getApiV1Authors({
148+
...options,
149+
...queryKey[0],
150+
signal,
151+
throwOnError: true
152+
});
153+
return data;
154+
},
155+
queryKey: getApiV1AuthorsQueryKey(options)
156+
});
157+
};

integrations/react-next-15/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"build": "next build"
77
},
88
"dependencies": {
9+
"@hey-api/client-next": "^0.2.1",
910
"@js-temporal/polyfill": "^0.4.4",
1011
"@tanstack/react-query": "workspace:*",
1112
"@tanstack/react-query-devtools": "workspace:*",

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)