Skip to content

Commit 1cbd2ae

Browse files
committed
React Query
1 parent 5493d81 commit 1cbd2ae

File tree

8 files changed

+232
-55
lines changed

8 files changed

+232
-55
lines changed

package-lock.json

Lines changed: 120 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"preview": "vite preview"
1010
},
1111
"dependencies": {
12+
"@tanstack/react-query": "4.28",
13+
"@tanstack/react-query-devtools": "4.28",
1214
"axios": "^1.3.4",
1315
"bootstrap": "^5.2.3",
1416
"react": "^18.2.0",

src/App.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import './App.css';
1+
import "./App.css";
2+
import PostList from "./react-query/PostList";
3+
import TodoList from "./react-query/TodoList";
24

35
function App() {
4-
return <h1>React Starter Project</h1>;
6+
return <PostList />;
57
}
68

79
export default App;

src/main.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
import 'bootstrap/dist/css/bootstrap.css';
2-
import React from 'react';
3-
import ReactDOM from 'react-dom/client';
4-
import App from './App';
5-
import './index.css';
1+
import "bootstrap/dist/css/bootstrap.css";
2+
import React from "react";
3+
import ReactDOM from "react-dom/client";
4+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
6+
import App from "./App";
7+
import "./index.css";
68

7-
ReactDOM.createRoot(
8-
document.getElementById('root') as HTMLElement
9-
).render(
9+
const queryClient = new QueryClient();
10+
11+
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
1012
<React.StrictMode>
11-
<App />
13+
<QueryClientProvider client={queryClient}>
14+
<App />
15+
<ReactQueryDevtools />
16+
</QueryClientProvider>
1217
</React.StrictMode>
1318
);

src/react-query/PostList.tsx

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
1-
import axios from 'axios';
2-
import { useEffect, useState } from 'react';
3-
4-
interface Post {
5-
id: number;
6-
title: string;
7-
body: string;
8-
userId: number;
9-
}
1+
import { useState } from "react";
2+
import usePosts from "./hooks/usePosts";
3+
import React from "react";
104

115
const PostList = () => {
12-
const [posts, setPosts] = useState<Post[]>([]);
13-
const [error, setError] = useState('');
6+
const pageSize = 10;
7+
const { data, error, isLoading, fetchNextPage, isFetchingNextPage } =
8+
usePosts({ pageSize });
149

15-
useEffect(() => {
16-
axios
17-
.get('https://jsonplaceholder.typicode.com/posts')
18-
.then((res) => setPosts(res.data))
19-
.catch((error) => setError(error));
20-
}, []);
10+
if (error) return <p>{error.message}</p>;
2111

22-
if (error) return <p>{error}</p>;
12+
if (isLoading) return <p>Loading...</p>;
2313

2414
return (
25-
<ul className="list-group">
26-
{posts.map((post) => (
27-
<li key={post.id} className="list-group-item">
28-
{post.title}
29-
</li>
30-
))}
31-
</ul>
15+
<>
16+
<ul className="list-group">
17+
{data.pages.map((page, index) => (
18+
<React.Fragment key={index}>
19+
{page.map((post) => (
20+
<li key={post.id} className="list-group-item">
21+
{post.title}
22+
</li>
23+
))}
24+
</React.Fragment>
25+
))}
26+
</ul>
27+
<button
28+
className="btn btn-primary my-3 ms-1"
29+
disabled={isFetchingNextPage}
30+
onClick={() => fetchNextPage()}
31+
>
32+
{isFetchingNextPage ? "Loading" : "Load More"}
33+
</button>
34+
</>
3235
);
3336
};
3437

src/react-query/TodoList.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
1-
import axios from 'axios';
2-
import React, { useEffect, useState } from 'react';
3-
4-
interface Todo {
5-
id: number;
6-
title: string;
7-
userId: number;
8-
completed: boolean;
9-
}
1+
import useTodos from "./hooks/useTodos";
102

113
const TodoList = () => {
12-
const [todos, setTodos] = useState<Todo[]>([]);
13-
const [error, setError] = useState('');
4+
const { data: todos, error, isLoading } = useTodos();
145

15-
useEffect(() => {
16-
axios
17-
.get('https://jsonplaceholder.typicode.com/todos')
18-
.then((res) => setTodos(res.data))
19-
.catch((error) => setError(error));
20-
}, []);
6+
if (isLoading) return <p>Loading...</p>;
217

22-
if (error) return <p>{error}</p>;
8+
if (error) return <p>{error.message}</p>;
239

2410
return (
2511
<ul className="list-group">
26-
{todos.map((todo) => (
12+
{todos?.map((todo) => (
2713
<li key={todo.id} className="list-group-item">
2814
{todo.title}
2915
</li>

src/react-query/hooks/usePosts.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
2+
import axios from "axios";
3+
4+
interface Post {
5+
id: number;
6+
title: string;
7+
body: string;
8+
userId: number;
9+
}
10+
11+
interface PostQuery {
12+
pageSize: number;
13+
}
14+
15+
const usePosts = (query: PostQuery) =>
16+
17+
useInfiniteQuery<Post[], Error>({
18+
queryKey: ['posts', query],
19+
queryFn: ({ pageParam = 1}) => axios
20+
.get<Post[]>('https://jsonplaceholder.typicode.com/posts', {
21+
params: {
22+
_start: (pageParam - 1) * query.pageSize,
23+
_limit: query.pageSize
24+
}
25+
})
26+
.then(res=>res.data),
27+
staleTime: 1 * 60 * 1000,
28+
keepPreviousData: true,
29+
getNextPageParam: (lastPage, allPages) => {
30+
return lastPage.length > 0 ? allPages.length + 1 : undefined;
31+
}
32+
});
33+
34+
35+
export default usePosts;

src/react-query/hooks/useTodos.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { useQuery } from "@tanstack/react-query";
2+
import axios from "axios";
3+
4+
interface Todo {
5+
id: number;
6+
title: string;
7+
userId: number;
8+
completed: boolean;
9+
}
10+
11+
const useTodos= () => {
12+
const fetchTodos = () =>
13+
axios
14+
.get<Todo[]>("https://jsonplaceholder.typicode.com/todos")
15+
.then((res) => res.data);
16+
17+
return useQuery<Todo[], Error>({
18+
queryKey: ["todos"],
19+
queryFn: fetchTodos,
20+
staleTime: 10 * 1000
21+
});
22+
};
23+
24+
export default useTodos;

0 commit comments

Comments
 (0)