Skip to content

Commit ed5e964

Browse files
committed
feat: hydrate jotai-tanstack-query queryClientAtom and TanStack/Query queryClient
1 parent f2659f4 commit ed5e964

File tree

6 files changed

+92
-27
lines changed

6 files changed

+92
-27
lines changed

examples/11_nextjs_app_router/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
"lint": "eslint"
1010
},
1111
"dependencies": {
12+
"@tanstack/react-query": "^5.90.10",
13+
"jotai": "^2.15.1",
14+
"jotai-tanstack-query": "workspace:*",
1215
"next": "16.0.3",
1316
"react": "19.2.0",
1417
"react-dom": "19.2.0"

examples/11_nextjs_app_router/src/app/posts/[postId]/_components/post.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
'use client'
22

3-
import { useQuery } from '@tanstack/react-query'
4-
import { getPost } from '../page'
53
import Link from 'next/link'
4+
import { useAtomValue, useSetAtom } from 'jotai'
5+
import { postIdAtom, postQueryAtom } from '../../../stores'
6+
import { useEffect } from 'react'
67

78
export const Post = ({ postId }: { postId: string }) => {
8-
const { data, isPending, isError } = useQuery({
9-
queryKey: ['posts', postId],
10-
queryFn: ({ queryKey: [, postId] }) => getPost(postId as string),
11-
})
9+
const setPostIdValue = useSetAtom(postIdAtom)
10+
useEffect(() => {
11+
setPostIdValue(postId)
12+
}, [postId, setPostIdValue])
13+
14+
const { data, isPending, isError, refetch } = useAtomValue(postQueryAtom)
1215
if (isPending) return <div>Loading...</div>
1316
if (isError) return <div>Error</div>
1417
return (
@@ -18,8 +21,16 @@ export const Post = ({ postId }: { postId: string }) => {
1821
<h1>Title: {data?.title}</h1>
1922
<div>Body: {data?.body}</div>
2023

21-
<div>
22-
<Link href={`/posts/${Number(postId) + 1}`}>Next post</Link>
24+
<div style={{ marginTop: '1rem' }}>
25+
<button onClick={() => refetch()}>
26+
Refetch post - only client-side
27+
</button>
28+
</div>
29+
30+
<div style={{ marginTop: '1rem' }}>
31+
<Link href={`/posts/${Number(postId) + 1}`}>
32+
Next post - only server-side
33+
</Link>
2334
</div>
2435
</div>
2536
)

examples/11_nextjs_app_router/src/app/posts/page.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@ export default function PostsPage() {
44
return (
55
<div>
66
Posts
7-
<Link href="/posts/1">Post 1</Link>
8-
<Link href="/posts/2">Post 2</Link>
9-
<Link href="/posts/3">Post 3</Link>
10-
<Link href="/posts/4">Post 4</Link>
11-
<Link href="/posts/5">Post 5</Link>
12-
<Link href="/posts/6">Post 6</Link>
13-
<Link href="/posts/7">Post 7</Link>
14-
<Link href="/posts/8">Post 8</Link>
15-
<Link href="/posts/9">Post 9</Link>
16-
<Link href="/posts/10">Post 10</Link>
7+
<div>
8+
<Link href="/posts/1">Post 1</Link>
9+
<br />
10+
<Link href="/posts/2">Post 2</Link>
11+
<br />
12+
<Link href="/posts/3">Post 3</Link>
13+
<br />
14+
<Link href="/posts/4">Post 4</Link>
15+
<br />
16+
<Link href="/posts/5">Post 5</Link>
17+
<br />
18+
<Link href="/posts/6">Post 6</Link>
19+
<br />
20+
<Link href="/posts/7">Post 7</Link>
21+
<br />
22+
<Link href="/posts/8">Post 8</Link>
23+
<br />
24+
<Link href="/posts/9">Post 9</Link>
25+
<br />
26+
<Link href="/posts/10">Post 10</Link>
27+
</div>
1728
</div>
1829
)
1930
}

examples/11_nextjs_app_router/src/app/providers.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@ import {
66
isServer,
77
QueryClient,
88
QueryClientProvider,
9+
QueryClientProviderProps,
910
} from '@tanstack/react-query'
11+
import { Provider } from 'jotai/react'
12+
import { useHydrateAtoms } from 'jotai/react/utils'
13+
import { queryClientAtom } from 'jotai-tanstack-query'
1014

15+
const HydrateAtoms = ({ client, children }: QueryClientProviderProps) => {
16+
useHydrateAtoms(new Map([[queryClientAtom, client]]))
17+
return children
18+
}
1119
function makeQueryClient() {
1220
return new QueryClient({
1321
defaultOptions: {
@@ -44,6 +52,10 @@ export default function Providers({ children }: { children: React.ReactNode }) {
4452
const queryClient = getQueryClient()
4553

4654
return (
47-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
55+
<QueryClientProvider client={queryClient}>
56+
<Provider>
57+
<HydrateAtoms client={queryClient}>{children}</HydrateAtoms>
58+
</Provider>
59+
</QueryClientProvider>
4860
)
4961
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { atom } from 'jotai'
2+
import { getPost } from './posts/[postId]/page'
3+
import { atomWithQuery } from 'jotai-tanstack-query'
4+
5+
export const postIdAtom = atom<string>('1')
6+
export const postQueryAtom = atomWithQuery((get) => ({
7+
queryKey: ['posts', get(postIdAtom)],
8+
queryFn: ({ queryKey: [, postId] }) => getPost(postId as string),
9+
staleTime: Infinity,
10+
refetchOnMount: false,
11+
refetchOnWindowFocus: false,
12+
}))

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)