snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
'use server'
import { revalidatePath } from 'next/cache'
import { countRef } from './make-query-client'
export async function queryExampleAction() {
await Promise.resolve()
countRef.current++
revalidatePath('/', 'page')
return undefined
}

View File

@@ -0,0 +1,36 @@
'use client'
import React from 'react'
import { useQuery } from '@tanstack/react-query'
import { Temporal } from '@js-temporal/polyfill'
export function ClientComponent() {
const query = useQuery({
queryKey: ['data'],
queryFn: async () => {
const { count } = await (
await fetch('http://localhost:3000/count')
).json()
return {
text: 'data from client',
date: Temporal.PlainDate.from('2023-01-01'),
count,
}
},
})
if (query.isPending) {
return <div>Loading...</div>
}
if (query.isError) {
return <div>An error has occurred!</div>
}
return (
<div>
{query.data.text} - {query.data.date.toJSON()} - {query.data.count}
</div>
)
}

View File

@@ -0,0 +1,5 @@
import { countRef } from '../make-query-client'
export const GET = () => {
return Response.json({ count: countRef.current })
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,22 @@
import React from 'react'
import Providers from './providers'
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}

View File

@@ -0,0 +1,53 @@
import { Temporal } from '@js-temporal/polyfill'
import { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query'
import { createTson } from 'tupleson'
import type { TsonType } from 'tupleson'
const plainDate = {
deserialize: (v) => Temporal.PlainDate.from(v),
key: 'PlainDate',
serialize: (v) => v.toJSON(),
test: (v) => v instanceof Temporal.PlainDate,
} satisfies TsonType<Temporal.PlainDate, string>
export const countRef = {
current: 0,
}
export const tson = createTson({
types: [plainDate],
})
export function makeQueryClient() {
return new QueryClient({
defaultOptions: {
hydrate: {
/**
* Called when the query is rebuilt from a prefetched
* promise, before the query data is put into the cache.
*/
deserializeData: (data) => {
return tson.deserialize(data)
},
},
queries: {
staleTime: 60 * 1000,
},
dehydrate: {
serializeData: (data) => {
return tson.serialize(data)
},
shouldDehydrateQuery: (query) => {
return (
defaultShouldDehydrateQuery(query) ||
query.state.status === 'pending'
)
},
shouldRedactErrors: (error) => {
// Next.js automatically redacts errors for us
return false
},
},
},
})
}

View File

@@ -0,0 +1,41 @@
import { headers } from 'next/headers'
import React from 'react'
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
import { Temporal } from '@js-temporal/polyfill'
import { ClientComponent } from './client-component'
import { makeQueryClient } from './make-query-client'
import { queryExampleAction } from './_action'
export default function Home() {
const queryClient = makeQueryClient()
queryClient.prefetchQuery({
queryKey: ['data'],
queryFn: async () => {
const { count } = await (
await fetch('http://localhost:3000/count', {
headers: await headers(),
})
).json()
return {
text: 'data from server',
date: Temporal.PlainDate.from('2024-01-01'),
count,
}
},
})
const state = dehydrate(queryClient)
return (
<main>
<HydrationBoundary state={state}>
<ClientComponent />
</HydrationBoundary>
<form action={queryExampleAction}>
<button type="submit">Increment</button>
</form>
</main>
)
}

View File

@@ -0,0 +1,39 @@
// In Next.js, this file would be called: app/providers.tsx
'use client'
// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top
import { QueryClientProvider, environmentManager } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import type { QueryClient } from '@tanstack/react-query'
import { makeQueryClient } from '@/app/make-query-client'
let browserQueryClient: QueryClient | undefined = undefined
function getQueryClient() {
if (environmentManager.isServer()) {
// Server: always make a new query client
return makeQueryClient()
} else {
// Browser: make a new query client if we don't already have one
// This is very important, so we don't re-make a new client if React
// suspends during the initial render. This may not be needed if we
// have a suspense boundary BELOW the creation of the query client
if (!browserQueryClient) browserQueryClient = makeQueryClient()
return browserQueryClient
}
}
export default function Providers({ children }: { children: React.ReactNode }) {
// NOTE: Avoid useState when initializing the query client if you don't
// have a suspense boundary between this and the code that may
// suspend because React will throw away the client on the initial
// render if it suspends and there is no boundary
const queryClient = getQueryClient()
return (
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools />
</QueryClientProvider>
)
}