Skip to content

Commit 135a616

Browse files
committed
rename post -> article in examples
1 parent 328b2bc commit 135a616

File tree

7 files changed

+141
-140
lines changed

7 files changed

+141
-140
lines changed

README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,53 +38,54 @@ When a Post is deleted, the list query is automatically invalidated and refetche
3838
import { QueryClient } from "@tanstack/react-query";
3939
import { HttpQueryBuilder } from "tanstack-query-builder/http";
4040

41-
type PostData = { id: number; title: string; body: string; userId: number };
41+
type ArticleData = { id: number; title: string; body: string; userId: number };
4242

4343
const client = new QueryClient();
4444

4545
const builder = new HttpQueryBuilder()
4646
.withClient(client)
47-
.withBaseUrl("https://jsonplaceholder.typicode.com")
47+
.withBaseUrl("https://api.example.com")
4848
.withTagTypes<{
49-
posts: PostData[];
49+
articles: ArticleData[];
5050
refreshable: unknown;
5151
}>();
5252

53-
const postsQuery = builder
54-
.withTags("refreshable", "posts")
55-
.withPath("/posts")
56-
.withData<PostData[]>();
53+
const articlesQuery = builder
54+
.withTags("refreshable", "articles")
55+
.withPath("/articles")
56+
.withData<ArticleData[]>();
5757

58-
const deletePostMutation = builder
59-
.withUpdates("posts")
58+
const deleteArticleMutation = builder
59+
.withUpdates("articles")
6060
.withMethod("delete")
61-
.withPath("/posts/:id");
61+
.withPath("/articles/:id");
6262

6363
export function MyApp() {
6464
const [refresh, { isPending: isRefreshing }] = builder.tags.useOperation({
6565
tags: "refreshable",
6666
});
67-
const posts = postsQuery.useQuery({});
68-
const deletePost = deletePostMutation.useMutation();
67+
const articles = articlesQuery.useQuery({});
68+
const deleteArticle = deleteArticleMutation.useMutation();
6969

70-
const onDelete = (id: number) => deletePost.mutateAsync({ params: { id } });
70+
const onDelete = (id: number) =>
71+
deleteArticle.mutateAsync({ params: { id } });
7172

72-
if (!posts.isSuccess) return <>Loading...</>;
73+
if (!articles.isSuccess) return <>Loading...</>;
7374

7475
return (
7576
<>
7677
<button onClick={() => refresh()} disabled={isRefreshing}>
77-
Refresh all posts
78+
Refresh all articles
7879
</button>
7980

80-
{posts.data.map((post) => (
81-
<div key={post.id}>
82-
<h2>{post.title}</h2>
83-
<p>{post.body}</p>
81+
{articles.data.map((article) => (
82+
<div key={article.id}>
83+
<h2>{article.title}</h2>
84+
<p>{article.body}</p>
8485

8586
<button
86-
onClick={() => onDelete(post.id)}
87-
disabled={deletePost.isPending}
87+
onClick={() => onDelete(article.id)}
88+
disabled={deleteArticle.isPending}
8889
>
8990
Delete
9091
</button>

examples/vite/src/App.tsx

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { QueryClientProvider } from '@tanstack/react-query';
22
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
33
import { useRef, useState } from 'react';
4-
import { CommentData, PostData, baseUrl, getMockHandlers } from 'tanstack-query-builder-example-mocks';
4+
import { ArticleData, CommentData, baseUrl, getMockHandlers } from 'tanstack-query-builder-example-mocks';
55
import { setupMSW } from 'tanstack-query-builder-example-mocks/setup-msw';
66
import { HttpQueryBuilder } from 'tanstack-query-builder/http';
77
import { queryClient } from './client';
@@ -10,29 +10,29 @@ import './index.css';
1010
await setupMSW(...getMockHandlers()).start({ onUnhandledRequest: 'bypass', quiet: true, waitUntilReady: true });
1111

1212
const builder = new HttpQueryBuilder().withClient(queryClient).withBaseUrl(baseUrl).withTagTypes<{
13-
post: PostData;
14-
posts: PostData[];
13+
article: ArticleData;
14+
articles: ArticleData[];
1515
comments: CommentData;
1616
refreshable: unknown;
1717
}>();
1818

1919
const resetMutation = builder.withPath('/reset').withMethod('post').withUpdates('*');
2020

21-
const postsQuery = builder
22-
.withTags('refreshable', 'posts')
23-
.withPath('/posts')
24-
.withData<PostData[]>()
21+
const articlesQuery = builder
22+
.withTags('refreshable', 'articles')
23+
.withPath('/articles')
24+
.withData<ArticleData[]>()
2525
.withSearch<{ page?: number }>()
2626
.withPagination({
2727
initialPageParam: { search: { page: 0 } },
2828
getNextPageParam: (prev, __, lastVars) => (!prev?.length ? null : { search: { page: (lastVars?.search?.page || 0) + 1 } }),
2929
});
3030

31-
const { useQuery: usePost, ...postQuery } = builder
31+
const { useQuery: useArticle, ...articleQuery } = builder
3232
.withTags('refreshable')
33-
.withPath('/posts/:id')
34-
.withData<PostData>()
35-
.withTags((ctx) => ({ type: 'post', id: ctx.data.id }))
33+
.withPath('/articles/:id')
34+
.withData<ArticleData>()
35+
.withTags((ctx) => ({ type: 'article', id: ctx.data.id }))
3636
.withPreprocessor<{ id: number }>((vars) => ({ ...vars, params: { id: vars.id } }))
3737
.withMiddleware(async (ctx, next) => {
3838
const res = await next(ctx);
@@ -43,21 +43,21 @@ const { useQuery: usePost, ...postQuery } = builder
4343
const commentsQuery = builder
4444
.withTags('refreshable')
4545
.withPath('/comments')
46-
.withSearch<{ postId: number | null }>()
46+
.withSearch<{ articleId: number | null }>()
4747
.withData<CommentData[]>();
4848

49-
const editPostMutation = builder
50-
.withPath('/posts/:id')
49+
const editArticleMutation = builder
50+
.withPath('/articles/:id')
5151
.withMethod('put')
52-
.withBody<Partial<PostData>>()
52+
.withBody<Partial<ArticleData>>()
5353
.withUpdates(
5454
{
55-
type: 'posts',
55+
type: 'articles',
5656
optimistic: true,
5757
updater: 'update-body-by-id',
5858
},
5959
(ctx) => ({
60-
type: 'post',
60+
type: 'article',
6161
id: ctx.vars.params.id,
6262
optimistic: true,
6363
updater: 'merge-body',
@@ -74,29 +74,29 @@ const editPostMutation = builder
7474
return res;
7575
});
7676

77-
const deletePostMutation = builder.withMethod('delete').withPath('/posts/:id').withUpdates({
78-
type: 'posts',
77+
const deleteArticleMutation = builder.withMethod('delete').withPath('/articles/:id').withUpdates({
78+
type: 'articles',
7979
optimistic: true,
8080
updater: 'delete-params-by-id',
8181
});
8282

8383
function AppCore() {
8484
const [enablePrefetch, setEnablePrefetch] = useState(false);
85-
const [postId, setPostId] = useState<number | null>(null);
85+
const [articleId, setArticleId] = useState<number | null>(null);
8686

87-
const posts = postsQuery.useInfiniteQuery({}, { enabled: postId == null });
87+
const articles = articlesQuery.useInfiniteQuery({}, { enabled: articleId == null });
8888
const reset = resetMutation.useMutation();
8989

90-
const deleteErrors = deletePostMutation.useMutationState(undefined, { status: 'error' }, (x) => x.state.variables?.params.id);
90+
const deleteErrors = deleteArticleMutation.useMutationState(undefined, { status: 'error' }, (x) => x.state.variables?.params.id);
9191

9292
const reload = () => builder.tags.reset({ tags: 'refreshable' });
9393

94-
if (postId != null) return <PostPage postId={postId} onBack={() => setPostId(null)} />;
94+
if (articleId != null) return <ArticlePage articleId={articleId} onBack={() => setArticleId(null)} />;
9595

9696
return (
9797
<>
9898
<div className="p-4">
99-
<button onClick={reload} disabled={posts.isFetching} className="btn btn-primary mr-2">
99+
<button onClick={reload} disabled={articles.isFetching} className="btn btn-primary mr-2">
100100
Reload
101101
</button>
102102

@@ -110,60 +110,60 @@ function AppCore() {
110110
</label>
111111
</div>
112112

113-
{posts.isLoading ? (
113+
{articles.isLoading ? (
114114
<div className="text-center">Loading...</div>
115-
) : posts.isError ? (
116-
<div className="text-red-500">{posts.error.message}</div>
115+
) : articles.isError ? (
116+
<div className="text-red-500">{articles.error.message}</div>
117117
) : (
118-
posts.data?.pages?.flat().map((post) => (
119-
<div key={post.id} className="p-4 border-b flex flex-row">
118+
articles.data?.pages?.flat().map((article) => (
119+
<div key={article.id} className="p-4 border-b flex flex-row">
120120
<div className="flex flex-col grow">
121121
<a>
122122
<h2
123-
onClick={() => setPostId(post.id)}
123+
onClick={() => setArticleId(article.id)}
124124
onMouseOver={() => {
125125
if (!enablePrefetch) return;
126-
postQuery.client.prefetch({ id: post.id });
127-
commentsQuery.client.prefetch({ search: { postId: post.id } });
126+
articleQuery.client.prefetch({ id: article.id });
127+
commentsQuery.client.prefetch({ search: { articleId: article.id } });
128128
}}
129129
className="text-xl font-bold cursor-pointer text-blue-800 hover:underline"
130130
>
131-
{post.id} - {post.title}
131+
{article.id} - {article.title}
132132
</h2>
133133
</a>
134134

135-
<p className="mt-2 whitespace-pre-wrap">{post.body}</p>
135+
<p className="mt-2 whitespace-pre-wrap">{article.body}</p>
136136
</div>
137137

138138
<div className="flex flex-col items-end">
139139
<button
140-
onClick={() => deletePostMutation.client.mutate({ params: { id: post.id } }).catch(() => {})}
141-
disabled={deletePostMutation.client.isMutating({ params: { id: post.id } }) > 0}
140+
onClick={() => deleteArticleMutation.client.mutate({ params: { id: article.id } }).catch(() => {})}
141+
disabled={deleteArticleMutation.client.isMutating({ params: { id: article.id } }) > 0}
142142
className="btn btn-danger mt-2"
143143
>
144144
Delete
145145
</button>
146146

147-
{deleteErrors.includes(post.id) && <span className="text-red-500 ml-4">Error deleting post</span>}
147+
{deleteErrors.includes(article.id) && <span className="text-red-500 ml-4">Error deleting article</span>}
148148
</div>
149149
</div>
150150
))
151151
)}
152152

153-
{posts.hasNextPage && (
154-
<button onClick={() => posts.fetchNextPage()} disabled={posts.isFetchingNextPage} className="btn btn-primary mt-4">
153+
{articles.hasNextPage && (
154+
<button onClick={() => articles.fetchNextPage()} disabled={articles.isFetchingNextPage} className="btn btn-primary mt-4">
155155
Load next page
156156
</button>
157157
)}
158158
</>
159159
);
160160
}
161161

162-
function PostPage({ postId, onBack }: { postId: number; onBack: () => void }) {
163-
const post = usePost({ id: postId });
164-
const comments = commentsQuery.useQuery({ search: { postId: postId } });
162+
function ArticlePage({ articleId, onBack }: { articleId: number; onBack: () => void }) {
163+
const article = useArticle({ id: articleId });
164+
const comments = commentsQuery.useQuery({ search: { articleId: articleId } });
165165
const [showEdit, setShowEdit] = useState(false);
166-
const editPost = editPostMutation.useMutation();
166+
const editArticle = editArticleMutation.useMutation();
167167

168168
const titleRef = useRef<HTMLInputElement>(null);
169169
const bodyRef = useRef<HTMLTextAreaElement>(null);
@@ -172,45 +172,45 @@ function PostPage({ postId, onBack }: { postId: number; onBack: () => void }) {
172172
<>
173173
{!showEdit ? (
174174
<>
175-
{post.isLoading ? (
175+
{article.isLoading ? (
176176
<div className="text-center">Loading...</div>
177-
) : post.isError ? (
178-
<div className="text-red-500">{post.error.message}</div>
177+
) : article.isError ? (
178+
<div className="text-red-500">{article.error.message}</div>
179179
) : (
180180
<div className="p-4">
181-
<h2 className="text-2xl font-bold">{post.data?.titleUppercase}</h2>
182-
<p className="mt-2 whitespace-pre-wrap">{post.data?.body}</p>
181+
<h2 className="text-2xl font-bold">{article.data?.titleUppercase}</h2>
182+
<p className="mt-2 whitespace-pre-wrap">{article.data?.body}</p>
183183
<button onClick={onBack} className="btn btn-secondary mt-4 mr-2">
184184
Back
185185
</button>
186-
<button onClick={() => setShowEdit(true)} disabled={editPost.isPending} className="btn btn-primary mt-4">
187-
Edit post
186+
<button onClick={() => setShowEdit(true)} disabled={editArticle.isPending} className="btn btn-primary mt-4">
187+
Edit article
188188
</button>
189189
</div>
190190
)}
191191
</>
192192
) : (
193193
<div className="p-4">
194-
<h2 className="text-2xl font-bold">Edit post</h2>
194+
<h2 className="text-2xl font-bold">Edit article</h2>
195195

196-
<input ref={titleRef} defaultValue={post.data?.title} className="block w-full mt-2 p-2 border rounded" />
196+
<input ref={titleRef} defaultValue={article.data?.title} className="block w-full mt-2 p-2 border rounded" />
197197

198-
<textarea ref={bodyRef} defaultValue={post.data?.body} className="block w-full mt-2 p-2 border rounded" />
198+
<textarea ref={bodyRef} defaultValue={article.data?.body} className="block w-full mt-2 p-2 border rounded" />
199199

200200
<button
201201
onClick={() => {
202-
editPost.mutateAsync({
203-
params: { id: postId },
202+
editArticle.mutateAsync({
203+
params: { id: articleId },
204204
body: {
205-
id: postId,
205+
id: articleId,
206206
title: titleRef.current!.value,
207207
body: bodyRef.current!.value,
208208
},
209209
});
210210

211211
setShowEdit(false);
212212
}}
213-
disabled={editPost.isPending}
213+
disabled={editArticle.isPending}
214214
className="btn btn-primary mt-4"
215215
>
216216
Save

examples/vite/src/SimpleExample.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
import { QueryClient } from '@tanstack/react-query';
2-
import { HttpQueryBuilder } from 'tanstack-query-builder';
2+
import { HttpQueryBuilder } from 'tanstack-query-builder/http';
33

4-
type PostData = { id: number; title: string; body: string; userId: number };
4+
type ArticleData = { id: number; title: string; body: string; userId: number };
55

66
const client = new QueryClient();
77

8-
const builder = new HttpQueryBuilder().withClient(client).withBaseUrl('https://jsonplaceholder.typicode.com').withTagTypes<{
9-
posts: PostData[];
8+
const builder = new HttpQueryBuilder().withClient(client).withBaseUrl('https://api.example.com').withTagTypes<{
9+
articles: ArticleData[];
1010
refreshable: unknown;
1111
}>();
1212

13-
const postsQuery = builder.withTags('refreshable', 'posts').withPath('/posts').withData<PostData[]>();
13+
const articlesQuery = builder.withTags('refreshable', 'articles').withPath('/articles').withData<ArticleData[]>();
1414

15-
const deletePostMutation = builder.withUpdates('posts').withMethod('delete').withPath('/posts/:id');
15+
const deleteArticleMutation = builder.withUpdates('articles').withMethod('delete').withPath('/articles/:id');
1616

1717
export function MyApp() {
1818
const [refresh, { isPending: isRefreshing }] = builder.tags.useOperation({ tags: 'refreshable' });
19-
const posts = postsQuery.useQuery({});
20-
const deletePost = deletePostMutation.useMutation();
19+
const articles = articlesQuery.useQuery({});
20+
const deleteArticle = deleteArticleMutation.useMutation();
2121

22-
const onDelete = (id: number) => deletePost.mutateAsync({ params: { id } });
22+
const onDelete = (id: number) => deleteArticle.mutateAsync({ params: { id } });
2323

24-
if (!posts.isSuccess) return <>Loading...</>;
24+
if (!articles.isSuccess) return <>Loading...</>;
2525

2626
return (
2727
<>
2828
<button onClick={() => refresh()} disabled={isRefreshing}>
29-
Refresh all posts
29+
Refresh all articles
3030
</button>
3131

32-
{posts.data.map((post) => (
33-
<div key={post.id}>
34-
<h2>{post.title}</h2>
35-
<p>{post.body}</p>
32+
{articles.data.map((article) => (
33+
<div key={article.id}>
34+
<h2>{article.title}</h2>
35+
<p>{article.body}</p>
3636

37-
<button onClick={() => onDelete(post.id)} disabled={deletePost.isPending}>
37+
<button onClick={() => onDelete(article.id)} disabled={deleteArticle.isPending}>
3838
Delete
3939
</button>
4040
</div>

0 commit comments

Comments
 (0)