Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

attempt repro #8682

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions integrations/react-next-15/app/authors/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
import { makeQueryClient } from '../make-query-client'
import { getApiV1AuthorsOptions } from '../query'
import { Authors } from '../client-component'

export default async function Page() {
const queryClient = makeQueryClient()

const data = await queryClient.fetchQuery({ ...getApiV1AuthorsOptions() })

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Authors />
</HydrationBoundary>
)
}
31 changes: 29 additions & 2 deletions integrations/react-next-15/app/client-component.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use client'

import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import Link from 'next/link'
import React from 'react'
import { useQuery } from '@tanstack/react-query'
import { Temporal } from '@js-temporal/polyfill'
import { getApiV1ActivitiesOptions, getApiV1AuthorsOptions } from './query'

export function ClientComponent() {
const query = useQuery({
Expand Down Expand Up @@ -34,3 +35,29 @@ export function ClientComponent() {
</div>
)
}

export const Activities = () => {
const { data: activities } = useSuspenseQuery({
...getApiV1ActivitiesOptions(),
})

return (
<div className="grid gap-8">
<Link href="/authors">Authors</Link>
<pre>{JSON.stringify(activities, null, 2)}</pre>
</div>
)
}

export const Authors = () => {
const { data: authors } = useSuspenseQuery({
...getApiV1AuthorsOptions(),
})

return (
<div className="grid gap-8">
<Link href="/">Activities</Link>
<pre>{JSON.stringify(authors, null, 2)}</pre>
</div>
)
}
16 changes: 11 additions & 5 deletions integrations/react-next-15/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { headers } from 'next/headers'
import React from 'react'
import React, { Suspense } from 'react'
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
import { Temporal } from '@js-temporal/polyfill'
import { ClientComponent } from './client-component'
import { Activities, ClientComponent } from './client-component'
import { makeQueryClient } from './make-query-client'
import { queryExampleAction } from './_action'
import { getApiV1ActivitiesOptions } from './query'

export default function Home() {
const queryClient = makeQueryClient()
Expand All @@ -26,16 +27,21 @@ export default function Home() {
},
})

void queryClient.prefetchQuery({ ...getApiV1ActivitiesOptions() })

const state = dehydrate(queryClient)

return (
<main>
<HydrationBoundary state={state}>
<ClientComponent />
<form action={queryExampleAction}>
<button type="submit">Increment</button>
</form>
<Suspense fallback={<div>Loading activities...</div>}>
<Activities />
</Suspense>
</HydrationBoundary>
<form action={queryExampleAction}>
<button type="submit">Increment</button>
</form>
</main>
)
}
190 changes: 190 additions & 0 deletions integrations/react-next-15/app/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { createClient, createConfig } from '@hey-api/client-next'
import { queryOptions } from '@tanstack/react-query'

import type {
Client,
ClientOptions,
CreateClientConfig,
Options as HeyApiOptions,
TDataShape,
} from '@hey-api/client-next'

export type Options<
TData extends TDataShape = TDataShape,
TThrowOnError extends boolean = boolean,
> = HeyApiOptions<TData, TThrowOnError> & {
/**
* You can provide a client instance returned by `createClient()` instead of
* individual options. This might be also useful if you want to implement a
* custom client.
*/
client?: Client
/**
* You can pass arbitrary values through the `meta` object. This can be
* used to access values that aren't defined as part of the SDK function.
*/
meta?: Record<string, unknown>
}

export const createClientConfig: CreateClientConfig = (config) => ({
...config,
baseUrl: 'https://fakerestapi.azurewebsites.net/',
})

export const _heyApiClient = createClient(
createClientConfig(
createConfig<ClientOptions>({
baseUrl: 'https://fakerestapi.azurewebsites.net',
}),
),
)

export type GetApiV1ActivitiesData = {
body?: never
path?: never
query?: never
url: '/api/v1/Activities'
}

export type Activity = {
id?: number
title?: string | null
dueDate?: string
completed?: boolean
}

export type Author = {
id?: number
idBook?: number
firstName?: string | null
lastName?: string | null
}

export type GetApiV1ActivitiesResponses = {
/**
* Success
*/
200: Array<Activity>
}

export type GetApiV1AuthorsData = {
body?: never
path?: never
query?: never
url: '/api/v1/Authors'
}

export type GetApiV1ActivitiesResponse =
GetApiV1ActivitiesResponses[keyof GetApiV1ActivitiesResponses]

export type QueryKey<TOptions extends Options> = [
Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & {
_id: string
_infinite?: boolean
},
]

const createQueryKey = <TOptions extends Options>(
id: string,
options?: TOptions,
infinite?: boolean,
): [QueryKey<TOptions>[0]] => {
const params: QueryKey<TOptions>[0] = {
_id: id,
baseUrl: (options?.client ?? _heyApiClient).getConfig().baseUrl,
} as QueryKey<TOptions>[0]
if (infinite) {
params._infinite = infinite
}
if (options?.body) {
params.body = options.body
}
if (options?.headers) {
params.headers = options.headers
}
if (options?.path) {
params.path = options.path
}
if (options?.query) {
params.query = options.query
}
return [params]
}

export const getApiV1Activities = <TThrowOnError extends boolean = false>(
options?: Options<GetApiV1ActivitiesData, TThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).get<
GetApiV1ActivitiesResponse,
unknown,
TThrowOnError
>({
url: '/api/v1/Activities',
...options,
})
}

export const getApiV1ActivitiesQueryKey = (
options?: Options<GetApiV1ActivitiesData>,
) => createQueryKey('getApiV1Activities', options)

export const getApiV1ActivitiesOptions = (
options?: Options<GetApiV1ActivitiesData>,
) => {
return queryOptions({
queryFn: async ({ queryKey, signal }) => {
const { data } = await getApiV1Activities({
...options,
...queryKey[0],
signal,
throwOnError: true,
})
return data
},
queryKey: getApiV1ActivitiesQueryKey(options),
})
}

export type GetApiV1AuthorsResponses = {
/**
* Success
*/
200: Array<Author>
}

export type GetApiV1AuthorsResponse =
GetApiV1AuthorsResponses[keyof GetApiV1AuthorsResponses]

export const getApiV1Authors = <TThrowOnError extends boolean = false>(
options?: Options<GetApiV1AuthorsData, TThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).get<
GetApiV1AuthorsResponse,
unknown,
TThrowOnError
>({
url: '/api/v1/Authors',
...options,
})
}

export const getApiV1AuthorsQueryKey = (
options?: Options<GetApiV1AuthorsData>,
) => createQueryKey('getApiV1Authors', options)

export const getApiV1AuthorsOptions = (
options?: Options<GetApiV1AuthorsData>,
) => {
return queryOptions({
queryFn: async ({ queryKey, signal }) => {
const { data } = await getApiV1Authors({
...options,
...queryKey[0],
signal,
throwOnError: true,
})
return data
},
queryKey: getApiV1AuthorsQueryKey(options),
})
}
1 change: 1 addition & 0 deletions integrations/react-next-15/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"build": "next build"
},
"dependencies": {
"@hey-api/client-next": "^0.2.1",
"@js-temporal/polyfill": "^0.4.4",
"@tanstack/react-query": "workspace:*",
"@tanstack/react-query-devtools": "workspace:*",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading