├── .gitignore
├── README.md
├── db.json
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── App.js
├── api
└── posts.js
├── components
├── NewPost.jsx
├── Post.jsx
└── Posts.jsx
├── hooks
└── posts.js
└── index.js
/.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-Query Tutorial | Consultar APIs, caché y sincronización de forma simple y eficiente 🚀
2 |
3 | ## Tutoriales
4 | ### Parte 1: Consultas
5 | [](https://www.youtube.com/watch?v=lNkAJCoXg6I "React-Query Tutorial | Consultar APIs, caché y sincronización de forma simple y eficiente 🚀")
6 |
7 | ### Parte 2: Mutaciones
8 | [](https://www.youtube.com/watch?v=X1qo8qEaWLg "React-Query Mutations Tutorial | Actualizar datos del servidor de forma simple y eficiente 🚀")
9 |
10 | ## Para iniciar la aplicación en modo desarrollo, usar los siguientes scripts
11 |
12 | ### `npm install`
13 | Instala las dependencias
14 | ### `npm start`
15 | Inicia la aplicación en modo desarrollo en el puerto `3000`
16 | ### `npm run server`
17 | Inicia el servidor de `json-server` en el puerto `3005` para probar el ejemplo
18 |
--------------------------------------------------------------------------------
/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "posts": [
3 | {
4 | "id": 1,
5 | "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
6 | "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
7 | },
8 | {
9 | "id": 2,
10 | "title": "qui est esse",
11 | "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
12 | },
13 | {
14 | "id": 3,
15 | "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
16 | "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
17 | },
18 | {
19 | "id": 4,
20 | "title": "eum et est occaecati",
21 | "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
22 | },
23 | {
24 | "id": 5,
25 | "title": "nesciunt quas odio",
26 | "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
27 | },
28 | {
29 | "id": 6,
30 | "title": "dolorem eum magni eos aperiam quia",
31 | "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
32 | },
33 | {
34 | "id": 7,
35 | "title": "magnam facilis autem",
36 | "body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
37 | },
38 | {
39 | "title": "aaa",
40 | "body": "aaa",
41 | "id": 8
42 | },
43 | {
44 | "title": "new post",
45 | "body": "aaa",
46 | "id": 9
47 | },
48 | {
49 | "title": "a",
50 | "body": "a",
51 | "id": 10
52 | },
53 | {
54 | "title": "a",
55 | "body": "a",
56 | "id": 11
57 | },
58 | {
59 | "title": "adf",
60 | "body": "asdf",
61 | "id": 12
62 | },
63 | {
64 | "title": "a",
65 | "body": "aa",
66 | "id": 13
67 | },
68 | {
69 | "title": "aaa",
70 | "body": "aaaa",
71 | "id": 14
72 | },
73 | {
74 | "title": "a",
75 | "body": "a",
76 | "id": 15
77 | }
78 | ]
79 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-query-yt",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "react-scripts start",
7 | "build": "react-scripts build",
8 | "test": "react-scripts test",
9 | "eject": "react-scripts eject",
10 | "server": "json-server --watch db.json --delay 1500 --port 3005"
11 | },
12 | "dependencies": {
13 | "@testing-library/jest-dom": "^5.16.1",
14 | "@testing-library/react": "^12.1.2",
15 | "@testing-library/user-event": "^13.5.0",
16 | "axios": "^0.24.0",
17 | "react": "^17.0.2",
18 | "react-dom": "^17.0.2",
19 | "react-query": "^3.34.7",
20 | "react-scripts": "5.0.0",
21 | "web-vitals": "^2.1.2"
22 | },
23 | "devDependencies": {
24 | "json-server": "^0.17.0"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ymulenll/react-query-tutorial/b4c5ad967733d90cd848d150b8858b56f74c87fb/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 |
28 |
34 | React Query - Demo
35 |
36 |
37 |
38 |
39 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ymulenll/react-query-tutorial/b4c5ad967733d90cd848d150b8858b56f74c87fb/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ymulenll/react-query-tutorial/b4c5ad967733d90cd848d150b8858b56f74c87fb/public/logo512.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/anchor-is-valid */
2 | import { useState } from "react";
3 | import NewPost from "./components/NewPost";
4 | import Post from "./components/Post";
5 | import Posts from "./components/Posts";
6 |
7 | export default function App() {
8 | const [postId, setPostId] = useState(-1);
9 |
10 | return (
11 |
12 | React-Query Demo
13 | {postId > -1 && (
14 |
19 | )}
20 | {postId > -1 ? (
21 |
22 | ) : (
23 |
31 | )}
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/src/api/posts.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | const API = process.env.REACT_APP_API || "http://localhost:3005";
4 |
5 | export const getPostById = async (postId) => {
6 | const { data } = await axios.get(`${API}/posts/${postId}`);
7 | return data;
8 | };
9 |
10 | export const getPosts = async () => {
11 | const { data } = await axios.get(`${API}/posts`);
12 | return data;
13 | };
14 |
15 | export const createNewPost = async (post) => {
16 | const { data } = await axios.post(`${API}/posts`, post);
17 | return data;
18 | };
19 |
--------------------------------------------------------------------------------
/src/components/NewPost.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { useMutatePost } from "../hooks/posts";
3 |
4 | function NewPost() {
5 | const [title, setTitle] = useState("");
6 | const [body, setBody] = useState("");
7 |
8 | const { mutate, error, isLoading, isSuccess, reset } = useMutatePost();
9 |
10 | const handleSubmit = async (e) => {
11 | e.preventDefault();
12 |
13 | mutate(
14 | { title, body },
15 | {
16 | onSuccess: () => {
17 | setTitle("");
18 | setBody("");
19 | },
20 | }
21 | );
22 | };
23 |
24 | return (
25 |
26 | Create Post:
27 |
78 |
79 | );
80 | }
81 |
82 | export default NewPost;
83 |
--------------------------------------------------------------------------------
/src/components/Post.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/anchor-is-valid */
2 | import { usePost } from "../hooks/posts";
3 |
4 | export default function Post({ postId }) {
5 | const { data: post, error, isLoading } = usePost(postId);
6 |
7 | if (isLoading) {
8 | return (
9 |
10 | Loading Post...
11 |
12 | );
13 | }
14 |
15 | if (error) {
16 | return (
17 |
18 | Error fetching post: {error.message}
19 |
20 | );
21 | }
22 |
23 | return (
24 |
25 | {post.title}
26 | {post.body}
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/src/components/Posts.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/anchor-is-valid */
2 | import { useQueryClient } from "react-query";
3 | import { usePosts } from "../hooks/posts";
4 |
5 | export default function Posts({ setPostId }) {
6 | const queryClient = useQueryClient();
7 | const {
8 | data: posts,
9 | error,
10 | isLoading,
11 | isFetching,
12 | // isIdle,
13 | // refetch,
14 | } = usePosts();
15 |
16 | // if (isIdle) {
17 | // return ;
18 | // }
19 |
20 | if (isLoading) {
21 | return (
22 |
23 | Loading Posts...
24 |
25 | );
26 | }
27 |
28 | if (error) {
29 | return (
30 |
31 | Error fetching posts: {error.message}
32 |
33 | );
34 | }
35 |
36 | return (
37 |
38 | Posts: {isFetching && }
39 |
54 |
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/src/hooks/posts.js:
--------------------------------------------------------------------------------
1 | import { useMutation, useQuery, useQueryClient } from "react-query";
2 | import { createNewPost, getPostById, getPosts } from "../api/posts";
3 |
4 | const key = "posts";
5 |
6 | export function useMutatePost() {
7 | const queryClient = useQueryClient();
8 |
9 | return useMutation(createNewPost, {
10 | onSuccess: (post) => {
11 | queryClient.setQueryData([key], (prevPosts) => prevPosts.concat(post));
12 | queryClient.invalidateQueries([key]);
13 | },
14 | });
15 | }
16 |
17 | export function usePosts() {
18 | return useQuery([key], getPosts);
19 | }
20 |
21 | export function usePost(postId) {
22 | return useQuery([key, postId], () => getPostById(postId));
23 | }
24 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from "react-dom";
2 | import { QueryClient, QueryClientProvider } from "react-query";
3 | import App from "./App";
4 | import { ReactQueryDevtools } from "react-query/devtools";
5 |
6 | const queryClient = new QueryClient();
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 | ,
13 | document.getElementById("root")
14 | );
15 |
--------------------------------------------------------------------------------