Skip to content

Commit dedca93

Browse files
Merge pull request #128
2 parents f781812 + 14ab21e commit dedca93

File tree

16 files changed

+275
-47
lines changed

16 files changed

+275
-47
lines changed

.github/workflows/cd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ jobs:
1717
cache: 'pnpm'
1818
cache-dependency-path: '**/pnpm-lock.yaml'
1919
- run: pnpm install --frozen-lockfile
20-
- run: pnpm test
2120
- run: pnpm run compile
21+
- run: pnpm test
2222
- run: pnpm publish --no-git-checks
2323
env:
2424
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: CI
22

33
on:
44
push:
5-
pull_request:
65

76
jobs:
87
test:
@@ -16,4 +15,5 @@ jobs:
1615
cache: 'pnpm'
1716
cache-dependency-path: '**/pnpm-lock.yaml'
1817
- run: pnpm install --frozen-lockfile
18+
- run: pnpm compile
1919
- run: pnpm test

.github/workflows/pr.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: Publish Preview
2-
on: [push, pull_request]
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize]
36

47
jobs:
58
build:

README.md

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
- [Suspense](#suspense)
1717
- [atomWithSuspenseQuery](#atomwithsuspensequery-usage)
1818
- [atomWithSuspenseInfiniteQuery](#atomwithsuspenseinfinitequery-usage)
19-
- [QueryClient Instance](#referencing-the-same-instance-of-query-client-in-your-project)
19+
- [QueryClient Instance](#referencing-the-same-instance-of-query-client)
2020
- [SSR Support](#ssr-support)
2121
- [Error Handling](#error-handling)
2222
- [Dev Tools](#devtools)
@@ -31,27 +31,26 @@ jotai-tanstack-query currently supports TanStack Query v5.
3131
In addition to `jotai`, you have to install `jotai-tanstack-query` and `@tanstack/query-core` to use the extension.
3232

3333
```bash
34-
yarn add jotai-tanstack-query @tanstack/query-core
34+
npm i jotai-tanstack-query @tanstack/query-core
3535
```
3636

3737
### Incremental Adoption
3838

39-
You can incrementally adopt `jotai-tanstack-query` in your app. It's not an all or nothing solution. You just have to ensure you are using the same QueryClient instance. [QueryClient Setup](#referencing-the-same-instance-of-query-client-in-your-project).
39+
You can incrementally adopt `jotai-tanstack-query` in your app. It's not an all or nothing solution. You just have to ensure you are using the same QueryClient instance. [same QueryClient](#referencing-the-same-instance-of-query-client).
4040

4141
```jsx
42-
# existing useQueryHook
43-
const { data, isPending, isError } = useQuery({
44-
queryKey: ['todos'],
45-
queryFn: fetchTodoList
46-
});
47-
48-
# jotai-tanstack-query
49-
const todosAtom = atomWithQuery(() => ({
50-
queryKey: ['todos'],
51-
}))
42+
// existing useQueryHook
43+
const { data, isPending, isError } = useQuery({
44+
queryKey: ['todos'],
45+
queryFn: fetchTodoList,
46+
})
5247

53-
const [{ data, isPending, isError }] = useAtom(todosAtom)
48+
// jotai-tanstack-query
49+
const todosAtom = atomWithQuery(() => ({
50+
queryKey: ['todos'],
51+
}))
5452

53+
const [{ data, isPending, isError }] = useAtom(todosAtom)
5554
```
5655

5756
### Exported functions
@@ -363,23 +362,23 @@ const Posts = () => {
363362
}
364363
```
365364

366-
### Referencing the same instance of Query Client in your project
365+
### Referencing the same instance of Query Client
367366

368-
Perhaps you have some custom hooks in your project that utilises the `useQueryClient()` hook to obtain the `QueryClient` object and call its methods.
367+
Perhaps you have some custom hooks in your project that utilizes the `useQueryClient()` hook to obtain the `QueryClient` object and call its methods.
369368

370-
To ensure that you reference the same `QueryClient` object, be sure to wrap the root of your project in a `<Provider>` and initialise `queryClientAtom` with the same `queryClient` value you provided to `QueryClientProvider`.
369+
To ensure that you reference the same `QueryClient` object, be sure to wrap the root of your project in a `<Provider>` and initialize `queryClientAtom` with the same `queryClient` value you provided to `QueryClientProvider`.
371370

372-
Without this step, `useQueryAtom` will reference a separate `QueryClient` from any hooks that utilise the `useQueryClient()` hook to get the queryClient.
371+
Without this step, `useQueryAtom` will reference a separate `QueryClient` from any hooks that utilize the `useQueryClient()` hook to get the queryClient.
373372

374373
Alternatively, you can specify your `queryClient` with `getQueryClient` parameter.
375374

376375
#### Example
377376

378377
In the example below, we have a mutation hook, `useTodoMutation` and a query `todosAtom`.
379378

380-
We included an initialisation step in our root `<App>` node.
379+
We included an initialization step in our root `<App>` node.
381380

382-
Although they reference methods same query key (`'todos'`), the `onSuccess` invalidation in `useTodoMutation` will not trigger **if the `Provider` initialisation step was not done.**
381+
Although they reference methods same query key (`'todos'`), the `onSuccess` invalidation in `useTodoMutation` will not trigger **if the `Provider` initialization step was not done.**
383382

384383
This will result in `todosAtom` showing stale data as it was not prompted to refetch.
385384

@@ -405,12 +404,16 @@ export const Root = () => {
405404
)
406405
}
407406

408-
export const todosAtom = atomWithQuery((get) => {
409-
return {
410-
queryKey: ['todos'],
411-
queryFn: () => fetch('/todos'),
412-
}
413-
})
407+
export const todosAtom = atomWithQuery(
408+
(get) => {
409+
return {
410+
queryKey: ["todos"],
411+
queryFn: () => fetch("/todos"),
412+
}
413+
},
414+
() => queryClient
415+
)
416+
414417

415418
export const useTodoMutation = () => {
416419
const queryClient = useQueryClient()
@@ -445,11 +448,7 @@ See [a working example](https://codesandbox.io/s/4gfp6z) to learn more.
445448
In order to use the Devtools, you need to install it additionally.
446449

447450
```bash
448-
$ npm i @tanstack/react-query-devtools
449-
# or
450-
$ pnpm add @tanstack/react-query-devtools
451-
# or
452-
$ yarn add @tanstack/react-query-devtools
451+
$ npm i @tanstack/react-query-devtools --save-dev
453452
```
454453

455454
All you have to do is put the `<ReactQueryDevtools />` within `<QueryClientProvider />`.

__tests__/atomWithQuery.spec.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ it('query basic test', async () => {
3535
}
3636

3737
if (isError) {
38-
return <>errorred</>
38+
return <>errored</>
3939
}
4040

4141
return (
@@ -83,7 +83,7 @@ it('async query basic test', async () => {
8383
const { data, isPending, isError } = userData
8484

8585
if (isPending) return <>loading</>
86-
if (isError) return <>errorred</>
86+
if (isError) return <>errored</>
8787

8888
return (
8989
<>
@@ -127,7 +127,7 @@ it('query refetch', async () => {
127127
}
128128

129129
if (isError) {
130-
return <>errorred</>
130+
return <>errored</>
131131
}
132132

133133
return (
@@ -187,7 +187,7 @@ it('query with enabled', async () => {
187187
}
188188

189189
if (isError) {
190-
return <>errorred</>
190+
return <>errored</>
191191
}
192192

193193
return <div>slug: {data.response.slug}</div>
@@ -257,7 +257,7 @@ it('query with enabled 2', async () => {
257257
}
258258

259259
if (isError) {
260-
return <>errorred</>
260+
return <>errored</>
261261
}
262262
return <div>slug: {data.response.slug}</div>
263263
}
@@ -340,7 +340,7 @@ it('query with enabled (#500)', async () => {
340340
}
341341

342342
if (isError) {
343-
return <>errorred</>
343+
return <>errored</>
344344
}
345345

346346
return <div>count: {data.response.count}</div>
@@ -452,7 +452,7 @@ it('query dependency test', async () => {
452452
}
453453

454454
if (isError) {
455-
return <>errorred</>
455+
return <>errored</>
456456
}
457457

458458
return (
@@ -507,7 +507,7 @@ it('query expected QueryCache test', async () => {
507507
}
508508

509509
if (isError) {
510-
return <>errorred</>
510+
return <>errored</>
511511
}
512512

513513
return (
@@ -673,7 +673,7 @@ it('renews the result when the query changes and a non stale cache is available'
673673
}
674674

675675
if (isError) {
676-
return <>errorred</>
676+
return <>errored</>
677677
}
678678

679679
return (

__tests__/atomWithSuspenseQuery.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe('intialData test', () => {
110110
const { data, isError } = countData
111111

112112
if (isError) {
113-
return <>errorred</>
113+
return <>errored</>
114114
}
115115

116116
const count = data?.response.count
@@ -154,7 +154,7 @@ describe('intialData test', () => {
154154
const [countData] = useAtom(countAtom)
155155
const { data, isError } = countData
156156
if (isError) {
157-
return <>errorred</>
157+
return <>errored</>
158158
}
159159
const count = data?.response.count
160160
return (

examples/07_queries/src/App.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import React from 'react'
21
import { Atom, atom } from 'jotai'
32
import { useAtom } from 'jotai/react'
43
import { type AtomWithQueryResult, atomWithQueries } from 'jotai-tanstack-query'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>jotai-tanstack-query example</title>
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
<script type="module" src="/src/index.tsx"></script>
11+
</body>
12+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "jotai-tanstack-query-example-incremental-adoption",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@tanstack/query-core": "latest",
7+
"@tanstack/react-query": "latest",
8+
"jotai": "latest",
9+
"jotai-tanstack-query": "*",
10+
"react": "latest",
11+
"react-dom": "latest"
12+
},
13+
"devDependencies": {
14+
"@types/react": "latest",
15+
"@types/react-dom": "latest",
16+
"@vitejs/plugin-react": "latest",
17+
"typescript": "latest",
18+
"vite": "latest"
19+
},
20+
"scripts": {
21+
"dev": "vite",
22+
"build": "vite build",
23+
"preview": "vite preview"
24+
}
25+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { QueryClient, useQuery } from '@tanstack/react-query'
2+
import { Provider, useAtom } from 'jotai/react'
3+
import { atom } from 'jotai/vanilla'
4+
import { atomWithQuery } from 'jotai-tanstack-query'
5+
import { QueryClientProvider } from 'jotai-tanstack-query/react'
6+
7+
const queryClient = new QueryClient()
8+
9+
const idAtom = atom(1)
10+
11+
const userAtom = atomWithQuery(
12+
(get) => ({
13+
queryKey: ['users', get(idAtom)],
14+
}),
15+
() => queryClient
16+
)
17+
18+
const UserDataRawFetch = () => {
19+
const [id] = useAtom(idAtom)
20+
const { data, isPending, isError } = useQuery({
21+
queryKey: ['users', id],
22+
queryFn: async ({ queryKey: [, id] }) => {
23+
const res = await fetch(
24+
`https://jsonplaceholder.typicode.com/users/${id}`
25+
)
26+
return res.json()
27+
},
28+
})
29+
30+
if (isPending) return <div>Loading...</div>
31+
if (isError) return <div>Error</div>
32+
33+
return (
34+
<>
35+
<h2>Tanstack Query</h2>
36+
<div>{JSON.stringify(data)}</div>
37+
</>
38+
)
39+
}
40+
41+
const UserData = () => {
42+
const [{ data, isPending, isError }] = useAtom(userAtom)
43+
44+
if (isPending) return <div>Loading...</div>
45+
if (isError) return <div>Error</div>
46+
47+
return (
48+
<>
49+
<h2>Jotai-Tanstack-Query</h2>
50+
<div>{JSON.stringify(data)}</div>
51+
</>
52+
)
53+
}
54+
55+
const Controls = () => {
56+
const [id, setId] = useAtom(idAtom)
57+
return (
58+
<>
59+
<div>
60+
ID: {id}{' '}
61+
<button type="button" onClick={() => setId((c) => c - 1)}>
62+
Prev
63+
</button>{' '}
64+
<button type="button" onClick={() => setId((c) => c + 1)}>
65+
Next
66+
</button>
67+
</div>
68+
<div>
69+
<button
70+
type="button"
71+
onClick={() =>
72+
queryClient.setQueryData(['users', id], (old: any) => {
73+
return {
74+
...old,
75+
name: old.name + '🔄',
76+
}
77+
})
78+
}>
79+
Update User Data
80+
</button>
81+
</div>
82+
</>
83+
)
84+
}
85+
86+
const App = () => (
87+
<>
88+
<QueryClientProvider client={queryClient}>
89+
<Provider>
90+
<Controls />
91+
<UserDataRawFetch />
92+
<UserData />
93+
</Provider>
94+
</QueryClientProvider>
95+
</>
96+
)
97+
98+
export default App

0 commit comments

Comments
 (0)