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

25
examples/react/nextjs/.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -0,0 +1,10 @@
# Example
In this simple example, we integrate React-Query seamlessly with Next.js data fetching methods to fetch queries in the server and hydrate them in the browser.
In addition to fetching and mutating data, React-Query analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run.
To run this example:
- `npm install`
- `npm run dev`

View File

@@ -0,0 +1,13 @@
// @ts-check
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
}
export default nextConfig

View File

@@ -0,0 +1,22 @@
{
"name": "@tanstack/query-example-react-nextjs",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --webpack",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@tanstack/react-query": "^5.102.8",
"@tanstack/react-query-devtools": "^5.102.8",
"next": "^16.0.7",
"react": "^19.2.1",
"react-dom": "^19.2.1"
},
"devDependencies": {
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"typescript": "5.8.3"
}
}

View File

@@ -0,0 +1,34 @@
import React from 'react'
import { useRouter } from 'next/router'
import Link from 'next/link'
export const Header = () => {
const { pathname } = useRouter()
return (
<header>
<Link href="/" className={pathname === '/' ? 'is-active' : ''}>
Home
</Link>
<Link
href="/client-only"
className={pathname === '/client-only' ? 'is-active' : ''}
>
Client-Only
</Link>
<style jsx>{`
header {
margin-bottom: 25px;
}
a {
font-size: 14px;
margin-right: 15px;
text-decoration: none;
}
.is-active {
text-decoration: underline;
}
`}</style>
</header>
)
}

View File

@@ -0,0 +1,19 @@
import React from 'react'
const InfoBox = ({ children }: { children: React.ReactNode }) => (
<div className="info">
<style jsx>{`
.info {
margin-top: 20px;
margin-bottom: 20px;
padding-top: 20px;
padding-bottom: 20px;
border-top: 1px solid #ececec;
border-bottom: 1px solid #ececec;
}
`}</style>
{children}
</div>
)
export { InfoBox }

View File

@@ -0,0 +1,50 @@
import React from 'react'
export const Layout = ({ children }: { children: React.ReactNode }) => {
return (
<main>
{children}
<style jsx global>{`
* {
font-family:
Menlo, Monaco, 'Lucida Console', 'Liberation Mono',
'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New',
monospace, serif;
}
body {
margin: 0;
padding: 25px 50px;
}
a {
color: #22bad9;
}
p {
font-size: 14px;
line-height: 24px;
}
article {
margin: 0 auto;
max-width: 650px;
}
button {
align-items: center;
background-color: #22bad9;
border: 0;
color: white;
display: flex;
padding: 5px 7px;
transition: background-color 0.3s;
}
button:active {
background-color: #1b9db7;
}
button:disabled {
background-color: #b5bebf;
}
button:focus {
outline: none;
}
`}</style>
</main>
)
}

View File

@@ -0,0 +1,67 @@
import React, { useState } from 'react'
import { usePosts } from '../hooks/usePosts'
export const PostList = () => {
const [postCount, setPostCount] = useState(10)
const { data, isPending, isFetching } = usePosts(postCount)
if (isPending) return <div>Loading</div>
return (
<section>
<ul>
{data?.map((post, index) => (
<li key={post.id}>
{index + 1}. {post.title}
</li>
))}
</ul>
{postCount <= 90 && (
<button
onClick={() => setPostCount(postCount + 10)}
disabled={isFetching}
>
{isFetching ? 'Loading...' : 'Show More'}
</button>
)}
<style jsx>{`
section {
padding-bottom: 20px;
}
li {
display: block;
margin-bottom: 10px;
}
div {
align-items: center;
display: flex;
}
a {
font-size: 14px;
margin-right: 10px;
text-decoration: none;
padding-bottom: 0;
border: 0;
}
span {
font-size: 14px;
margin-right: 5px;
}
ul {
margin: 0;
padding: 0;
}
button:before {
align-self: center;
border-style: solid;
border-width: 6px 4px 0 4px;
border-color: #ffffff transparent transparent transparent;
content: '';
height: 0;
margin-right: 5px;
width: 0;
}
`}</style>
</section>
)
}

View File

@@ -0,0 +1,4 @@
export * from './Header'
export * from './InfoBox'
export * from './Layout'
export * from './PostList'

View File

@@ -0,0 +1,22 @@
import { useQuery } from '@tanstack/react-query'
type Post = {
id: number
title: string
body: string
}
const fetchPosts = async (limit = 10): Promise<Array<Post>> => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
const data = await response.json()
return data.filter((x: Post) => x.id <= limit)
}
const usePosts = (limit: number) => {
return useQuery({
queryKey: ['posts', limit],
queryFn: () => fetchPosts(limit),
})
}
export { usePosts, fetchPosts }

View File

@@ -0,0 +1,21 @@
import React from 'react'
import {
HydrationBoundary,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import type { AppProps } from 'next/app'
export default function MyApp({ Component, pageProps }: AppProps) {
const [queryClient] = React.useState(() => new QueryClient())
return (
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<Component {...pageProps} />
</HydrationBoundary>
<ReactQueryDevtools />
</QueryClientProvider>
)
}

View File

@@ -0,0 +1,14 @@
import React from 'react'
import { Header, InfoBox, Layout, PostList } from '../components'
const ClientOnly = () => {
return (
<Layout>
<Header />
<InfoBox>ℹ️ This data is loaded on client and not prefetched</InfoBox>
<PostList />
</Layout>
)
}
export default ClientOnly

View File

@@ -0,0 +1,33 @@
import React from 'react'
import { QueryClient, dehydrate, noop } from '@tanstack/react-query'
import { Header, InfoBox, Layout, PostList } from '../components'
import { fetchPosts } from '../hooks/usePosts'
const Home = () => {
return (
<Layout>
<Header />
<InfoBox>ℹ️ This page shows how to use SSG with React-Query.</InfoBox>
<PostList />
</Layout>
)
}
export async function getStaticProps() {
const queryClient = new QueryClient()
await queryClient
.query({
queryKey: ['posts', 10],
queryFn: () => fetchPosts(10),
})
.catch(noop)
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
export default Home

View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"target": "ES2017"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}