11import { QueryClientProvider } from '@tanstack/react-query' ;
22import { ReactQueryDevtools } from '@tanstack/react-query-devtools' ;
33import { 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' ;
55import { setupMSW } from 'tanstack-query-builder-example-mocks/setup-msw' ;
66import { HttpQueryBuilder } from 'tanstack-query-builder/http' ;
77import { queryClient } from './client' ;
@@ -10,29 +10,29 @@ import './index.css';
1010await setupMSW ( ...getMockHandlers ( ) ) . start ( { onUnhandledRequest : 'bypass' , quiet : true , waitUntilReady : true } ) ;
1111
1212const 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
1919const 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
4343const 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
8383function 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
0 commit comments