Skip to content

Commit 37a1136

Browse files
committed
add infinite scrolling example
1 parent df8317f commit 37a1136

File tree

24 files changed

+981
-9
lines changed

24 files changed

+981
-9
lines changed

apps/0-json-server/db.json

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4333,13 +4333,6 @@
43334333
"name": "ex eaque eum natus",
43344334
"email": "Emma@joanny.ca",
43354335
"body": "perspiciatis quis doloremque\nveniam nisi eos velit sed\nid totam inventore voluptatem laborum et eveniet\naut aut aut maxime quia temporibus ut omnis"
4336-
},
4337-
{
4338-
"body": "asdf",
4339-
"email": "user@mailinator.com",
4340-
"name": "User",
4341-
"postId": 2,
4342-
"id": 501
43434336
}
43444337
]
43454338
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React Query</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "3.2-vite-reactquery-infinite",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite --port 33032",
8+
"build": "tsc && vite build",
9+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"@mantine/core": "7.12.2",
14+
"@mantine/hooks": "7.12.2",
15+
"@tabler/icons-react": "^3.17.0",
16+
"@tanstack/react-query": "^5.56.2",
17+
"@tanstack/react-query-devtools": "^5.56.2",
18+
"mantine-react-table": "^2.0.0-beta.6",
19+
"react": "^18.3.1",
20+
"react-dom": "^18.3.1",
21+
"react-router-dom": "^6.26.2"
22+
},
23+
"devDependencies": {
24+
"@types/react": "^18.3.7",
25+
"@types/react-dom": "^18.3.0",
26+
"@typescript-eslint/eslint-plugin": "^8.6.0",
27+
"@typescript-eslint/parser": "^8.6.0",
28+
"@vitejs/plugin-react": "^4.3.1",
29+
"eslint": "^9.10.0",
30+
"eslint-plugin-react-hooks": "^4.6.2",
31+
"eslint-plugin-react-refresh": "^0.4.12",
32+
"postcss": "^8.4.47",
33+
"postcss-preset-mantine": "1.17.0",
34+
"postcss-simple-vars": "^7.0.1",
35+
"typescript": "^5.6.2",
36+
"vite": "^5.4.6"
37+
}
38+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
plugins: {
3+
"postcss-preset-mantine": {},
4+
"postcss-simple-vars": {
5+
variables: {
6+
"mantine-breakpoint-xs": "36em",
7+
"mantine-breakpoint-sm": "48em",
8+
"mantine-breakpoint-md": "62em",
9+
"mantine-breakpoint-lg": "75em",
10+
"mantine-breakpoint-xl": "88em",
11+
},
12+
},
13+
},
14+
};
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { AppRoutes } from "./AppRoutes";
2+
import { AppProviders } from "./AppProviders";
3+
import "@mantine/core/styles.css";
4+
import "mantine-react-table/styles.css";
5+
6+
export const App = () => {
7+
return (
8+
<AppProviders>
9+
<AppRoutes />
10+
</AppProviders>
11+
);
12+
};
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {
2+
Anchor,
3+
AppShell,
4+
Breadcrumbs,
5+
Burger,
6+
Group,
7+
Stack,
8+
} from "@mantine/core";
9+
import { useDisclosure } from "@mantine/hooks";
10+
import { IconHome, IconUsersGroup } from "@tabler/icons-react";
11+
import { useMemo } from "react";
12+
import { Link, useLocation } from "react-router-dom";
13+
14+
interface AppLayoutProps {
15+
children: React.ReactNode;
16+
}
17+
18+
const links = [
19+
{
20+
icon: <IconHome size="1rem" />,
21+
color: "blue",
22+
label: "Home Feed",
23+
href: "/",
24+
},
25+
{
26+
icon: <IconUsersGroup size="1rem" />,
27+
color: "teal",
28+
label: "Users",
29+
href: "/users",
30+
},
31+
];
32+
33+
export function AppLayout({ children }: AppLayoutProps) {
34+
const { pathname } = useLocation();
35+
36+
const breadCrumbLinks = useMemo(() => {
37+
const routes = pathname.split("/");
38+
routes.shift();
39+
const links: string[] = [];
40+
for (let i = 0; i < routes.length + 1; i++) {
41+
if (routes[i] && routes[i] !== "/")
42+
if (routes[i] === "posts") {
43+
links.push(`/`);
44+
} else links.push(`/${routes.slice(0, i + 1).join("/")}`);
45+
}
46+
return links;
47+
}, [pathname]);
48+
49+
if (breadCrumbLinks.length === 1) {
50+
breadCrumbLinks.unshift("/");
51+
}
52+
53+
const [opened, { toggle }] = useDisclosure();
54+
55+
return (
56+
<AppShell
57+
header={{ height: 60 }}
58+
navbar={{ width: 300, breakpoint: "sm", collapsed: { mobile: !opened } }}
59+
padding="xl"
60+
>
61+
<AppShell.Header>
62+
<Group h="100%" px="md">
63+
<Burger opened={opened} onClick={toggle} size="sm" />
64+
Vite with React Query
65+
</Group>
66+
</AppShell.Header>
67+
<AppShell.Navbar p="md">
68+
{links.map((link) => (
69+
<Anchor component={Link} key={link.label} to={link.href}>
70+
{link.label}
71+
</Anchor>
72+
))}
73+
</AppShell.Navbar>
74+
<AppShell.Main mb="xl">
75+
<Stack gap="md" mt="lg">
76+
<Breadcrumbs aria-label="breadcrumb" pb="md">
77+
{breadCrumbLinks.map((link, index) => (
78+
<Anchor
79+
c="inherit"
80+
component={Link}
81+
key={index}
82+
td="none"
83+
to={link}
84+
tt="capitalize"
85+
style={{
86+
cursor: "pointer",
87+
}}
88+
>
89+
{link === "/" ? "Home Feed" : link.split("/").pop()}
90+
</Anchor>
91+
))}
92+
</Breadcrumbs>
93+
{children}
94+
</Stack>
95+
</AppShell.Main>
96+
</AppShell>
97+
);
98+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { lazy, Suspense, type ReactNode } from "react";
2+
import { MantineProvider } from "@mantine/core";
3+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4+
import { BrowserRouter } from "react-router-dom";
5+
import { theme } from "./theme";
6+
7+
const ReactQueryDevtoolsProduction = lazy(() =>
8+
import("@tanstack/react-query-devtools/production").then((d) => ({
9+
default: d.ReactQueryDevtools,
10+
})),
11+
);
12+
13+
const queryClient = new QueryClient({
14+
defaultOptions: {
15+
queries: {
16+
staleTime: 1000 * 10, // 10 seconds
17+
},
18+
},
19+
});
20+
21+
interface Props {
22+
children: ReactNode;
23+
}
24+
25+
export const AppProviders = ({ children }: Props) => {
26+
return (
27+
<BrowserRouter>
28+
<QueryClientProvider client={queryClient}>
29+
<MantineProvider theme={theme}>
30+
{children}
31+
<Suspense fallback={null}>
32+
<ReactQueryDevtoolsProduction />
33+
</Suspense>
34+
</MantineProvider>
35+
</QueryClientProvider>
36+
</BrowserRouter>
37+
);
38+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Route, Routes } from "react-router-dom";
2+
import { AppLayout } from "./AppLayout";
3+
import { HomePage } from "./pages/HomePage";
4+
import { PostPage } from "./pages/PostPage";
5+
import { UsersPage } from "./pages/UsersPage";
6+
import { UserPage } from "./pages/UserPage";
7+
8+
export const AppRoutes = () => {
9+
return (
10+
<AppLayout>
11+
<Routes>
12+
<Route path="/" element={<HomePage />} />
13+
<Route path="/posts/:id" element={<PostPage />} />
14+
<Route path="/users" element={<UsersPage />} />
15+
<Route path="/users/:id" element={<UserPage />} />
16+
</Routes>
17+
</AppLayout>
18+
);
19+
};

0 commit comments

Comments
 (0)