├── src ├── App.css ├── react-app-env.d.ts ├── types │ └── Tutorial.ts ├── index.css ├── reportWebVitals.ts ├── index.tsx ├── services │ └── TutorialService.ts ├── logo.svg └── App.tsx ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── react-query-axios-typescript.png ├── .gitignore ├── tsconfig.json ├── package.json └── README.md /src/App.css: -------------------------------------------------------------------------------- 1 | #app { 2 | max-width: 600px; 3 | } -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-query-axios-typescript/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-query-axios-typescript/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-query-axios-typescript/HEAD/public/logo512.png -------------------------------------------------------------------------------- /react-query-axios-typescript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-query-axios-typescript/HEAD/react-query-axios-typescript.png -------------------------------------------------------------------------------- /src/types/Tutorial.ts: -------------------------------------------------------------------------------- 1 | export default interface Tutorial { 2 | id?: any | null, 3 | title: string, 4 | description: string, 5 | published?: boolean, 6 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | import { QueryClient, QueryClientProvider } from "react-query"; 8 | const queryClient = new QueryClient(); 9 | 10 | ReactDOM.render( 11 | 12 | 13 | 14 | 15 | , 16 | document.getElementById('root') 17 | ); 18 | 19 | // If you want to start measuring performance in your app, pass a function 20 | // to log results (for example: reportWebVitals(console.log)) 21 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 22 | reportWebVitals(); 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-query-axios-typescript", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "axios": "^0.24.0", 14 | "react": "^17.0.2", 15 | "react-dom": "^17.0.2", 16 | "react-query": "^3.29.0", 17 | "react-scripts": "4.0.3", 18 | "typescript": "^4.1.2", 19 | "web-vitals": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/services/TutorialService.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import Tutorial from "../types/Tutorial"; 3 | 4 | const apiClient = axios.create({ 5 | baseURL: "http://localhost:8080/api", 6 | headers: { 7 | "Content-type": "application/json", 8 | }, 9 | }); 10 | 11 | const findAll = async () => { 12 | const response = await apiClient.get("/tutorials"); 13 | return response.data; 14 | } 15 | 16 | const findById = async (id: any) => { 17 | const response = await apiClient.get(`/tutorials/${id}`); 18 | return response.data; 19 | } 20 | 21 | const findByTitle = async (title: string) => { 22 | const response = await apiClient.get(`/tutorials?title=${title}`); 23 | return response.data; 24 | } 25 | 26 | const create = async ({ title, description }: Tutorial) => { 27 | const response = await apiClient.post("/tutorials", { title, description }); 28 | return response.data; 29 | } 30 | 31 | const update = async (id: any, { title, description, published }: Tutorial) => { 32 | const response = await apiClient.put(`/tutorials/${id}`, { title, description, published }); 33 | return response.data; 34 | } 35 | 36 | const deleteById = async (id: any) => { 37 | const response = await apiClient.delete(`/tutorials/${id}`); 38 | return response.data; 39 | } 40 | 41 | const deleteAll = async () => { 42 | const response = await apiClient.delete("/tutorials"); 43 | return response.data; 44 | } 45 | 46 | const TutorialService = { 47 | findAll, 48 | findById, 49 | findByTitle, 50 | create, 51 | update, 52 | deleteById, 53 | deleteAll 54 | } 55 | 56 | export default TutorialService; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | 31 | React Query Axios Typescript example 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Query with Axios and Typescript example 2 | 3 | React Client with React Query and Axios (Typescript) to make CRUD requests to Rest API in that: 4 | 5 | - React Query Axios Typescript GET request: get all Tutorials, get Tutorial by Id, find Tutorial by title 6 | - React Query Axios Typescript POST request: create new Tutorial 7 | - React Query Axios Typescript PUT request: update an existing Tutorial 8 | - React Query Axios Typescript DELETE request: delete a Tutorial, delete all Tutorials 9 | 10 | ![react-query-axios-typescript](react-query-axios-typescript.png) 11 | 12 | For instruction, please visit: 13 | > [React Query Axios (Typescript) - Get/Post/Put/Delete example with Rest API](https://www.bezkoder.com/react-query-axios-typescript/) 14 | 15 | Related Posts: 16 | > [React Hooks Typescript example Project with Axios and Web API](https://bezkoder.com/react-typescript-api-call/) 17 | 18 | > [React Hook Form Typescript example with Validation](https://www.bezkoder.com/react-hook-form-typescript/) 19 | 20 | > [React Table example: CRUD App with react-table v7](https://www.bezkoder.com/react-table-example-hooks-crud/) 21 | 22 | > [React Hooks File Upload example](https://bezkoder.com/react-hooks-file-upload/) 23 | 24 | > [React Hooks: JWT Authentication & Authorization example](https://bezkoder.com/react-hooks-jwt-auth/) 25 | 26 | > [React + Redux + Hooks: JWT Authentication & Authorization example](https://bezkoder.com/react-hooks-redux-login-registration-example/) 27 | 28 | Fullstack with Node Express: 29 | 30 | > [React + Node Express + MySQL](https://www.bezkoder.com/react-node-express-mysql/) 31 | 32 | > [React + Node Express + PostgreSQL](https://www.bezkoder.com/react-node-express-postgresql/) 33 | 34 | > [React + Node Express + MongoDB](https://www.bezkoder.com/react-node-express-mongodb-mern-stack/) 35 | 36 | Fullstack with Spring Boot: 37 | 38 | > [React + Spring Boot + MySQL](https://www.bezkoder.com/react-spring-boot-crud/) 39 | 40 | > [React + Spring Boot + PostgreSQL](https://www.bezkoder.com/spring-boot-react-postgresql/) 41 | 42 | > [React + Spring Boot + MongoDB](https://www.bezkoder.com/react-spring-boot-mongodb/) 43 | 44 | Fullstack with Django: 45 | 46 | > [React + Django Rest Framework](https://www.bezkoder.com/django-react-axios-rest-framework/) 47 | 48 | Serverless with Firebase: 49 | 50 | > [React Typescript Firebase example: Build CRUD App](https://www.bezkoder.com/firebase-typescript-react/) 51 | 52 | > [React Typescript Firestore example: Build CRUD App](https://www.bezkoder.com/react-typescript-firestore/) 53 | 54 | Integration (run back-end & front-end on same server/port) 55 | 56 | > [How to integrate React with Spring Boot](https://www.bezkoder.com/integrate-reactjs-spring-boot/) 57 | 58 | > [Integrate React with Node Express on same Server/Port](https://www.bezkoder.com/integrate-react-express-same-server-port/) 59 | 60 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useQuery, useMutation } from "react-query"; 3 | import "./App.css"; 4 | 5 | import Tutorial from "./types/Tutorial" 6 | import TutorialService from "./services/TutorialService" 7 | 8 | const App: React.FC = () => { 9 | const [getId, setGetId] = useState(""); 10 | const [getTitle, setGetTitle] = useState(""); 11 | 12 | const [postTitle, setPostTitle] = useState(""); 13 | const [postDescription, setPostDescription] = useState(""); 14 | 15 | const [putId, setPutId] = useState(""); 16 | const [putTitle, setPutTitle] = useState(""); 17 | const [putDescription, setPutDescription] = useState(""); 18 | const [putPublished, setPutPublished] = useState(false); 19 | 20 | const [deleteId, setDeleteId] = useState(""); 21 | 22 | const [getResult, setGetResult] = useState(null); 23 | const [postResult, setPostResult] = useState(null); 24 | const [putResult, setPutResult] = useState(null); 25 | const [deleteResult, setDeleteResult] = useState(null); 26 | 27 | const fortmatResponse = (res: any) => { 28 | return JSON.stringify(res, null, 2); 29 | }; 30 | 31 | const { isLoading: isLoadingTutorials, refetch: getAllTutorials } = useQuery( 32 | "query-tutorials", 33 | async () => { 34 | return await TutorialService.findAll(); 35 | }, 36 | { 37 | enabled: false, 38 | onSuccess: (res) => { 39 | setGetResult(fortmatResponse(res)); 40 | }, 41 | onError: (err: any) => { 42 | setGetResult(fortmatResponse(err.response?.data || err)); 43 | }, 44 | } 45 | ); 46 | 47 | useEffect(() => { 48 | if (isLoadingTutorials) setGetResult("loading..."); 49 | }, [isLoadingTutorials]); 50 | 51 | function getAllData() { 52 | try { 53 | getAllTutorials(); 54 | } catch (err) { 55 | setGetResult(fortmatResponse(err)); 56 | } 57 | } 58 | 59 | const { isLoading: isLoadingTutorial, refetch: getTutorialById } = useQuery( 60 | "query-tutorial-by-id", 61 | async () => { 62 | return await TutorialService.findById(getId); 63 | }, 64 | { 65 | enabled: false, 66 | retry: 1, 67 | onSuccess: (res) => { 68 | setGetResult(fortmatResponse(res)); 69 | }, 70 | onError: (err: any) => { 71 | setGetResult(fortmatResponse(err.response?.data || err)); 72 | }, 73 | } 74 | ); 75 | 76 | useEffect(() => { 77 | if (isLoadingTutorial) setGetResult("loading..."); 78 | }, [isLoadingTutorial]); 79 | 80 | function getDataById() { 81 | if (getId) { 82 | try { 83 | getTutorialById(); 84 | } catch (err) { 85 | setGetResult(fortmatResponse(err)); 86 | } 87 | } 88 | } 89 | 90 | const { isLoading: isSearchingTutorial, refetch: findTutorialsByTitle } = useQuery( 91 | "query-tutorials-by-title", // ["query-tutorials-by-title", getTitle], 92 | async () => { 93 | return await TutorialService.findByTitle(getTitle); 94 | }, 95 | { 96 | enabled: false, 97 | retry: 1, 98 | onSuccess: (res) => { 99 | setGetResult(fortmatResponse(res)); 100 | }, 101 | onError: (err: any) => { 102 | setGetResult(fortmatResponse(err.response?.data || err)); 103 | }, 104 | } 105 | ); 106 | 107 | useEffect(() => { 108 | if (isSearchingTutorial) setGetResult("searching..."); 109 | }, [isSearchingTutorial]); 110 | 111 | function getDataByTitle() { 112 | if (getTitle) { 113 | try { 114 | findTutorialsByTitle(); 115 | } catch (err) { 116 | setGetResult(fortmatResponse(err)); 117 | } 118 | } 119 | } 120 | 121 | const { isLoading: isPostingTutorial, mutate: postTutorial } = useMutation( 122 | async () => { 123 | return await TutorialService.create( 124 | { 125 | title: postTitle, 126 | description: postDescription 127 | }); 128 | }, 129 | { 130 | onSuccess: (res) => { 131 | setPostResult(fortmatResponse(res)); 132 | }, 133 | onError: (err: any) => { 134 | setPostResult(fortmatResponse(err.response?.data || err)); 135 | }, 136 | } 137 | ); 138 | 139 | useEffect(() => { 140 | if (isPostingTutorial) setPostResult("posting..."); 141 | }, [isPostingTutorial]); 142 | 143 | function postData() { 144 | try { 145 | postTutorial(); 146 | } catch (err) { 147 | setPostResult(fortmatResponse(err)); 148 | } 149 | } 150 | 151 | const { isLoading: isUpdatingTutorial, mutate: updateTutorial } = useMutation( 152 | async () => { 153 | return await TutorialService.update( 154 | putId, 155 | { 156 | title: putTitle, 157 | description: putDescription, 158 | published: putPublished 159 | }); 160 | }, 161 | { 162 | onSuccess: (res) => { 163 | setPutResult(fortmatResponse(res)); 164 | }, 165 | onError: (err: any) => { 166 | setPutResult(fortmatResponse(err.response?.data || err)); 167 | }, 168 | } 169 | ); 170 | 171 | useEffect(() => { 172 | if (isUpdatingTutorial) setPutResult("updating..."); 173 | }, [isUpdatingTutorial]); 174 | 175 | function putData() { 176 | if (putId) { 177 | try { 178 | updateTutorial(); 179 | } catch (err) { 180 | setPutResult(fortmatResponse(err)); 181 | } 182 | } 183 | } 184 | 185 | const { isLoading: isDeletingTutorials, mutate: deleteAllTutorials } = useMutation( 186 | async () => { 187 | return await TutorialService.deleteAll(); 188 | }, 189 | { 190 | onSuccess: (res) => { 191 | setDeleteResult(fortmatResponse(res)); 192 | }, 193 | onError: (err: any) => { 194 | setDeleteResult(fortmatResponse(err.response?.data || err)); 195 | }, 196 | } 197 | ); 198 | 199 | useEffect(() => { 200 | if (isDeletingTutorials) setDeleteResult("deleting..."); 201 | }, [isDeletingTutorials]); 202 | 203 | function deleteAllData() { 204 | try { 205 | deleteAllTutorials(); 206 | } catch (err) { 207 | setDeleteResult(fortmatResponse(err)); 208 | } 209 | } 210 | 211 | const { isLoading: isDeletingTutorial, mutate: deleteTutorial } = useMutation( 212 | async () => { 213 | return await TutorialService.deleteById(deleteId); 214 | }, 215 | { 216 | onSuccess: (res) => { 217 | setDeleteResult(fortmatResponse(res)); 218 | }, 219 | onError: (err: any) => { 220 | setDeleteResult(fortmatResponse(err.response?.data || err)); 221 | }, 222 | } 223 | ); 224 | 225 | useEffect(() => { 226 | if (isDeletingTutorial) setDeleteResult("deleting..."); 227 | }, [isDeletingTutorial]); 228 | 229 | function deleteDataById() { 230 | if (deleteId) { 231 | try { 232 | deleteTutorial(); 233 | } catch (err) { 234 | setDeleteResult(fortmatResponse(err)); 235 | } 236 | } 237 | } 238 | 239 | const clearGetOutput = () => { 240 | setGetResult(null); 241 | }; 242 | 243 | const clearPostOutput = () => { 244 | setPostResult(null); 245 | }; 246 | 247 | const clearPutOutput = () => { 248 | setPutResult(null); 249 | }; 250 | 251 | const clearDeleteOutput = () => { 252 | setDeleteResult(null); 253 | }; 254 | 255 | return ( 256 |
257 |

React Query Axios Typescript example

258 | 259 |
260 |
React Query Axios Typescript GET - BezKoder.com
261 |
262 |
263 | 266 | 267 | setGetId(e.target.value)} 271 | className="form-control ml-2" 272 | placeholder="Id" 273 | /> 274 |
275 | 278 |
279 | 280 | setGetTitle(e.target.value)} 284 | className="form-control ml-2" 285 | placeholder="Title" 286 | /> 287 |
288 | 294 |
295 | 296 | 302 |
303 | 304 | {getResult && ( 305 |
306 |
{getResult}
307 |
308 | )} 309 |
310 |
311 | 312 |
313 |
React Query Axios Typescript POST - BezKoder.com
314 |
315 |
316 | setPostTitle(e.target.value)} 320 | className="form-control" 321 | placeholder="Title" 322 | /> 323 |
324 |
325 | setPostDescription(e.target.value)} 329 | className="form-control" 330 | placeholder="Description" 331 | /> 332 |
333 | 336 | 342 | 343 | {postResult && ( 344 |
345 |
{postResult}
346 |
347 | )} 348 |
349 |
350 | 351 |
352 |
React Query Axios Typescript PUT - BezKoder.com
353 |
354 |
355 | setPutId(e.target.value)} 359 | className="form-control" 360 | placeholder="Id" 361 | /> 362 |
363 |
364 | setPutTitle(e.target.value)} 368 | className="form-control" 369 | placeholder="Title" 370 | /> 371 |
372 |
373 | setPutDescription(e.target.value)} 377 | className="form-control" 378 | placeholder="Description" 379 | /> 380 |
381 |
382 | setPutPublished(e.target.checked)} 387 | className="form-check-input" 388 | /> 389 | 392 |
393 | 396 | 402 | 403 | {putResult && ( 404 |
405 |
{putResult}
406 |
407 | )} 408 |
409 |
410 | 411 |
412 |
413 | React Query Axios Typescript DELETE - BezKoder.com 414 |
415 |
416 |
417 | 420 | 421 | setDeleteId(e.target.value)} 425 | className="form-control ml-2" 426 | placeholder="Id" 427 | /> 428 |
429 | 435 |
436 | 437 | 443 |
444 | 445 | {deleteResult && ( 446 |
447 |
{deleteResult}
448 |
449 | )} 450 |
451 |
452 |
453 | ); 454 | } 455 | 456 | export default App; 457 | --------------------------------------------------------------------------------