Skip to content

Commit 5d51652

Browse files
committed
feat: initial commit
added working example of @tanstack/react-form with zod validation and an array input field
0 parents  commit 5d51652

28 files changed

+5232
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local

.prettierrc.json5

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
trailingComma: "all",
3+
tabWidth: 2,
4+
semi: false,
5+
singleQuote: false,
6+
}

README.md

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
Welcome to your new TanStack app!
2+
3+
# Getting Started
4+
5+
To run this application:
6+
7+
```bash
8+
pnpm install
9+
pnpm start
10+
```
11+
12+
# Building For Production
13+
14+
To build this application for production:
15+
16+
```bash
17+
pnpm build
18+
```
19+
20+
## Testing
21+
22+
This project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:
23+
24+
```bash
25+
pnpm test
26+
```
27+
28+
## Styling
29+
30+
This project uses [Tailwind CSS](https://tailwindcss.com/) for styling.
31+
32+
33+
34+
35+
36+
## Routing
37+
This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.
38+
39+
### Adding A Route
40+
41+
To add a new route to your application just add another a new file in the `./src/routes` directory.
42+
43+
TanStack will automatically generate the content of the route file for you.
44+
45+
Now that you have two routes you can use a `Link` component to navigate between them.
46+
47+
### Adding Links
48+
49+
To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.
50+
51+
```tsx
52+
import { Link } from "@tanstack/react-router";
53+
```
54+
55+
Then anywhere in your JSX you can use it like so:
56+
57+
```tsx
58+
<Link to="/about">About</Link>
59+
```
60+
61+
This will create a link that will navigate to the `/about` route.
62+
63+
More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).
64+
65+
### Using A Layout
66+
67+
In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.
68+
69+
Here is an example layout that includes a header:
70+
71+
```tsx
72+
import { Outlet, createRootRoute } from '@tanstack/react-router'
73+
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
74+
75+
import { Link } from "@tanstack/react-router";
76+
77+
export const Route = createRootRoute({
78+
component: () => (
79+
<>
80+
<header>
81+
<nav>
82+
<Link to="/">Home</Link>
83+
<Link to="/about">About</Link>
84+
</nav>
85+
</header>
86+
<Outlet />
87+
<TanStackRouterDevtools />
88+
</>
89+
),
90+
})
91+
```
92+
93+
The `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.
94+
95+
More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).
96+
97+
98+
## Data Fetching
99+
100+
There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.
101+
102+
For example:
103+
104+
```tsx
105+
const peopleRoute = createRoute({
106+
getParentRoute: () => rootRoute,
107+
path: "/people",
108+
loader: async () => {
109+
const response = await fetch("https://swapi.dev/api/people");
110+
return response.json() as Promise<{
111+
results: {
112+
name: string;
113+
}[];
114+
}>;
115+
},
116+
component: () => {
117+
const data = peopleRoute.useLoaderData();
118+
return (
119+
<ul>
120+
{data.results.map((person) => (
121+
<li key={person.name}>{person.name}</li>
122+
))}
123+
</ul>
124+
);
125+
},
126+
});
127+
```
128+
129+
Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).
130+
131+
### React-Query
132+
133+
React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.
134+
135+
First add your dependencies:
136+
137+
```bash
138+
pnpm add @tanstack/react-query @tanstack/react-query-devtools
139+
```
140+
141+
Next we'll need to create a query client and provider. We recommend putting those in `main.tsx`.
142+
143+
```tsx
144+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
145+
146+
// ...
147+
148+
const queryClient = new QueryClient();
149+
150+
// ...
151+
152+
if (!rootElement.innerHTML) {
153+
const root = ReactDOM.createRoot(rootElement);
154+
155+
root.render(
156+
<QueryClientProvider client={queryClient}>
157+
<RouterProvider router={router} />
158+
</QueryClientProvider>
159+
);
160+
}
161+
```
162+
163+
You can also add TanStack Query Devtools to the root route (optional).
164+
165+
```tsx
166+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
167+
168+
const rootRoute = createRootRoute({
169+
component: () => (
170+
<>
171+
<Outlet />
172+
<ReactQueryDevtools buttonPosition="top-right" />
173+
<TanStackRouterDevtools />
174+
</>
175+
),
176+
});
177+
```
178+
179+
Now you can use `useQuery` to fetch your data.
180+
181+
```tsx
182+
import { useQuery } from "@tanstack/react-query";
183+
184+
import "./App.css";
185+
186+
function App() {
187+
const { data } = useQuery({
188+
queryKey: ["people"],
189+
queryFn: () =>
190+
fetch("https://swapi.dev/api/people")
191+
.then((res) => res.json())
192+
.then((data) => data.results as { name: string }[]),
193+
initialData: [],
194+
});
195+
196+
return (
197+
<div>
198+
<ul>
199+
{data.map((person) => (
200+
<li key={person.name}>{person.name}</li>
201+
))}
202+
</ul>
203+
</div>
204+
);
205+
}
206+
207+
export default App;
208+
```
209+
210+
You can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).
211+
212+
## State Management
213+
214+
Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.
215+
216+
First you need to add TanStack Store as a dependency:
217+
218+
```bash
219+
pnpm add @tanstack/store
220+
```
221+
222+
Now let's create a simple counter in the `src/App.tsx` file as a demonstration.
223+
224+
```tsx
225+
import { useStore } from "@tanstack/react-store";
226+
import { Store } from "@tanstack/store";
227+
import "./App.css";
228+
229+
const countStore = new Store(0);
230+
231+
function App() {
232+
const count = useStore(countStore);
233+
return (
234+
<div>
235+
<button onClick={() => countStore.setState((n) => n + 1)}>
236+
Increment - {count}
237+
</button>
238+
</div>
239+
);
240+
}
241+
242+
export default App;
243+
```
244+
245+
One of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.
246+
247+
Let's check this out by doubling the count using derived state.
248+
249+
```tsx
250+
import { useStore } from "@tanstack/react-store";
251+
import { Store, Derived } from "@tanstack/store";
252+
import "./App.css";
253+
254+
const countStore = new Store(0);
255+
256+
const doubledStore = new Derived({
257+
fn: () => countStore.state * 2,
258+
deps: [countStore],
259+
});
260+
doubledStore.mount();
261+
262+
function App() {
263+
const count = useStore(countStore);
264+
const doubledCount = useStore(doubledStore);
265+
266+
return (
267+
<div>
268+
<button onClick={() => countStore.setState((n) => n + 1)}>
269+
Increment - {count}
270+
</button>
271+
<div>Doubled - {doubledCount}</div>
272+
</div>
273+
);
274+
}
275+
276+
export default App;
277+
```
278+
279+
We use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.
280+
281+
Once we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.
282+
283+
You can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).
284+
285+
# Demo files
286+
287+
Files prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.
288+
289+
# Learn More
290+
291+
You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).

components.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "",
8+
"css": "src/styles.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
},
20+
"iconLibrary": "lucide"
21+
}

index.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<link rel="icon" href="/favicon.ico" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Web site created using create-tsrouter-app"
11+
/>
12+
<link rel="apple-touch-icon" href="/logo192.png" />
13+
<link rel="manifest" href="/manifest.json" />
14+
<title>Create TanStack App - wishlist</title>
15+
</head>
16+
<body>
17+
<div id="app"></div>
18+
<script type="module" src="/src/main.tsx"></script>
19+
</body>
20+
</html>

package.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "wishlist",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"start": "vite --port 3000",
7+
"build": "vite build && tsc",
8+
"serve": "vite preview",
9+
"test": "vitest run"
10+
},
11+
"dependencies": {
12+
"@radix-ui/react-alert-dialog": "^1.1.6",
13+
"@radix-ui/react-label": "^2.1.2",
14+
"@radix-ui/react-select": "^2.1.6",
15+
"@radix-ui/react-slot": "^1.1.2",
16+
"@tailwindcss/vite": "^4.0.6",
17+
"@tanstack/react-form": "^1.0.5",
18+
"@tanstack/react-router": "^1.114.3",
19+
"@tanstack/react-router-devtools": "^1.114.3",
20+
"@tanstack/router-plugin": "^1.114.3",
21+
"class-variance-authority": "^0.7.1",
22+
"clsx": "^2.1.1",
23+
"lucide-react": "^0.482.0",
24+
"next-themes": "^0.4.6",
25+
"react": "^19.0.0",
26+
"react-dom": "^19.0.0",
27+
"sonner": "^2.0.1",
28+
"tailwind-merge": "^3.0.2",
29+
"tailwindcss": "^4.0.6",
30+
"tailwindcss-animate": "^1.0.7",
31+
"zod": "^3.24.2"
32+
},
33+
"devDependencies": {
34+
"@testing-library/dom": "^10.4.0",
35+
"@testing-library/react": "^16.2.0",
36+
"@types/react": "^19.0.8",
37+
"@types/react-dom": "^19.0.3",
38+
"@vitejs/plugin-react": "^4.3.4",
39+
"jsdom": "^26.0.0",
40+
"prettier": "3.5.3",
41+
"typescript": "^5.7.2",
42+
"vite": "^6.1.0",
43+
"vitest": "^3.0.5",
44+
"web-vitals": "^4.2.4"
45+
}
46+
}

0 commit comments

Comments
 (0)