Skip to content

Commit 146c0ac

Browse files
authored
Merge branch 'main' into fix/backshlash-path-parameters
2 parents 51fff1a + 231230e commit 146c0ac

File tree

48 files changed

+153
-99
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+153
-99
lines changed

docs/router/framework/react/comparison.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Feature/Capability Key:
6161
| Async Scroll Restoration || 🛑 | 🛑 |
6262
| Router Invalidation ||||
6363
| Runtime Route Manipulation (Fog of War) | 🛑 |||
64+
| Parallel Routes | 🛑 | 🛑 ||
6465
| -- | -- | -- | -- |
6566
| **Full Stack** | -- | -- | -- |
6667
| SSR ||||

docs/router/framework/react/routing/file-naming-conventions.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ title: File Naming Conventions
44

55
File-based routing requires that you follow a few simple file naming conventions to ensure that your routes are generated correctly. The concepts these conventions enable are covered in detail in the [Route Trees & Nesting](./route-trees.md) guide.
66

7-
| Feature | Description |
8-
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
9-
| **`__root.tsx`** | The root route file must be named `__root.tsx` and must be placed in the root of the configured `routesDirectory`. |
10-
| **`.` Separator** | Routes can use the `.` character to denote a nested route. For example, `blog.post` will be generated as a child of `blog`. |
11-
| **`$` Token** | Route segments with the `$` token are parameterized and will extract the value from the URL pathname as a route `param`. |
12-
| **`_` Prefix** | Route segments with the `_` prefix are considered to be pathless layout routes and will not be used when matching its child routes against the URL pathname. |
13-
| **`_` Suffix** | Route segments with the `_` suffix exclude the route from being nested under any parent routes. |
14-
| **`(folder)` folder name pattern** | A folder that matches this pattern is treated as a **route group**, preventing the folder from being included in the route's URL path. |
15-
| **`index` Token** | Route segments ending with the `index` token (before any file extensions) will match the parent route when the URL pathname matches the parent route exactly. This can be configured via the `indexToken` configuration option, see [options](#options). |
16-
| **`.route.tsx` File Type** | When using directories to organise routes, the `route` suffix can be used to create a route file at the directory's path. For example, `blog.post.route.tsx` or `blog/post/route.tsx` can be used as the route file for the `/blog/post` route. This can be configured via the `routeToken` configuration option, see [options](#options). |
7+
| Feature | Description |
8+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9+
| **`__root.tsx`** | The root route file must be named `__root.tsx` and must be placed in the root of the configured `routesDirectory`. |
10+
| **`.` Separator** | Routes can use the `.` character to denote a nested route. For example, `blog.post` will be generated as a child of `blog`. |
11+
| **`$` Token** | Route segments with the `$` token are parameterized and will extract the value from the URL pathname as a route `param`. |
12+
| **`_` Prefix** | Route segments with the `_` prefix are considered to be pathless layout routes and will not be used when matching its child routes against the URL pathname. |
13+
| **`_` Suffix** | Route segments with the `_` suffix exclude the route from being nested under any parent routes. |
14+
| **`(folder)` folder name pattern** | A folder that matches this pattern is treated as a **route group**, preventing the folder from being included in the route's URL path. |
15+
| **`index` Token** | Route segments ending with the `index` token (before any file extensions) will match the parent route when the URL pathname matches the parent route exactly. This can be configured via the `indexToken` configuration option, see [options](../../../api/file-based-routing.md#indextoken). |
16+
| **`.route.tsx` File Type** | When using directories to organise routes, the `route` suffix can be used to create a route file at the directory's path. For example, `blog.post.route.tsx` or `blog/post/route.tsx` can be used as the route file for the `/blog/post` route. This can be configured via the `routeToken` configuration option, see [options](../../../api/file-based-routing.md#routetoken). |
1717

1818
> **💡 Remember:** The file-naming conventions for your project could be affected by what [options](../../../api/file-based-routing.md) are configured.
1919

docs/start/framework/react/learn-the-basics.md

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,23 +275,57 @@ Here's a quick example of how you can use server functions to perform a mutation
275275

276276
```tsx
277277
import { createServerFn } from '@tanstack/react-start'
278+
import { z } from 'zod'
279+
import { dbUpdateUser } from '...'
278280

279281
const UserSchema = z.object({
280282
id: z.string(),
281283
name: z.string(),
282284
})
285+
export type User = z.infer<typeof UserSchema>
283286

284-
const updateUser = createServerFn({ method: 'POST' })
287+
export const updateUser = createServerFn({ method: 'POST' })
285288
.validator(UserSchema)
286-
.handler(async ({ data }) => {
287-
return db
288-
.update(users)
289-
.set({ name: data.name })
290-
.where(eq(users.id, data.id))
291-
})
289+
.handler(({ data }) => dbUpdateUser(data))
292290

293291
// Somewhere else in your application
294-
await updateUser({ data: { id: '1', name: 'John' } })
292+
import { useQueryClient } from '@tanstack/react-query'
293+
import { useRouter } from '@tanstack/react-router'
294+
import { useServerFunction } from '@tanstack/react-start'
295+
import { updateUser, type User } from '...'
296+
297+
export function useUpdateUser() {
298+
const router = useRouter()
299+
const queryClient = useQueryClient()
300+
const _updateUser = useServerFunction(updateUser)
301+
302+
return useCallback(
303+
async (user: User) => {
304+
const result = await _updateUser({ data: user })
305+
306+
router.invalidate()
307+
queryClient.invalidateQueries({
308+
queryKey: ['users', 'updateUser', user.id],
309+
})
310+
311+
return result
312+
},
313+
[router, queryClient, _updateUser],
314+
)
315+
}
316+
317+
// Somewhere else in your application
318+
import { useUpdateUser } from '...'
319+
320+
function MyComponent() {
321+
const updateUser = useUpdateUser()
322+
const onClick = useCallback(async () => {
323+
await updateUser({ id: '1', name: 'John' })
324+
console.log('Updated user')
325+
}, [updateUser])
326+
327+
return <button onClick={onClick}>Click Me</button>
328+
}
295329
```
296330

297331
To learn more about mutations, check out the [mutations guide](/router/latest/docs/framework/react/guide/data-mutations).

examples/react/basic-ssr-file-based/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@tanstack/react-router": "^1.116.0",
1515
"@tanstack/react-router-devtools": "^1.116.0",
1616
"@tanstack/router-plugin": "^1.116.1",
17-
"@tanstack/react-start": "^1.116.1",
17+
"@tanstack/react-start": "^1.116.2",
1818
"get-port": "^7.1.0",
1919
"react": "^19.0.0",
2020
"react-dom": "^19.0.0",

examples/react/basic-ssr-streaming-file-based/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@tanstack/react-router": "^1.116.0",
1515
"@tanstack/react-router-devtools": "^1.116.0",
1616
"@tanstack/router-plugin": "^1.116.1",
17-
"@tanstack/react-start": "^1.116.1",
17+
"@tanstack/react-start": "^1.116.2",
1818
"get-port": "^7.1.0",
1919
"react": "^19.0.0",
2020
"react-dom": "^19.0.0",

examples/react/start-bare/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"dependencies": {
1212
"@tanstack/react-router": "^1.116.0",
1313
"@tanstack/react-router-devtools": "^1.116.0",
14-
"@tanstack/react-start": "^1.116.1",
14+
"@tanstack/react-start": "^1.116.2",
1515
"react": "^19.0.0",
1616
"react-dom": "^19.0.0",
1717
"vinxi": "0.5.3",

examples/react/start-basic-auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@prisma/client": "5.22.0",
1414
"@tanstack/react-router": "^1.116.0",
1515
"@tanstack/react-router-devtools": "^1.116.0",
16-
"@tanstack/react-start": "^1.116.1",
16+
"@tanstack/react-start": "^1.116.2",
1717
"prisma": "^5.22.0",
1818
"react": "^19.0.0",
1919
"react-dom": "^19.0.0",

examples/react/start-basic-react-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@tanstack/react-router": "^1.116.0",
1515
"@tanstack/react-router-with-query": "^1.116.0",
1616
"@tanstack/react-router-devtools": "^1.116.0",
17-
"@tanstack/react-start": "^1.116.1",
17+
"@tanstack/react-start": "^1.116.2",
1818
"react": "^19.0.0",
1919
"react-dom": "^19.0.0",
2020
"redaxios": "^0.5.1",

examples/react/start-basic-rsc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@babel/plugin-syntax-typescript": "^7.25.9",
1313
"@tanstack/react-router": "^1.116.0",
1414
"@tanstack/react-router-devtools": "^1.116.0",
15-
"@tanstack/react-start": "^1.116.1",
15+
"@tanstack/react-start": "^1.116.2",
1616
"react": "^19.0.0",
1717
"react-dom": "^19.0.0",
1818
"redaxios": "^0.5.1",

examples/react/start-basic-static/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"dependencies": {
1212
"@tanstack/react-router": "^1.116.0",
1313
"@tanstack/react-router-devtools": "^1.116.0",
14-
"@tanstack/react-start": "^1.116.1",
14+
"@tanstack/react-start": "^1.116.2",
1515
"react": "^19.0.0",
1616
"react-dom": "^19.0.0",
1717
"redaxios": "^0.5.1",

examples/react/start-basic/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,18 @@
1111
"dependencies": {
1212
"@tanstack/react-router": "^1.116.0",
1313
"@tanstack/react-router-devtools": "^1.116.0",
14-
"@tanstack/react-start": "^1.116.1",
14+
"@tanstack/react-start": "^1.116.2",
1515
"react": "^19.0.0",
1616
"react-dom": "^19.0.0",
17-
"redaxios": "^0.5.1",
1817
"tailwind-merge": "^2.6.0",
1918
"vinxi": "0.5.3"
2019
},
2120
"devDependencies": {
2221
"@types/node": "^22.5.4",
2322
"@types/react": "^19.0.8",
2423
"@types/react-dom": "^19.0.3",
25-
"postcss": "^8.5.1",
2624
"autoprefixer": "^10.4.20",
25+
"postcss": "^8.5.1",
2726
"tailwindcss": "^3.4.17",
2827
"typescript": "^5.7.2",
2928
"vite-tsconfig-paths": "^5.1.4"

examples/react/start-basic/src/routes/api/users.$id.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import { json } from '@tanstack/react-start'
22
import { createAPIFileRoute } from '@tanstack/react-start/api'
3-
import axios from 'redaxios'
43
import type { User } from '../../utils/users'
54

65
export const APIRoute = createAPIFileRoute('/api/users/$id')({
76
GET: async ({ request, params }) => {
87
console.info(`Fetching users by id=${params.id}... @`, request.url)
98
try {
10-
const res = await axios.get<User>(
9+
const res = await fetch(
1110
'https://jsonplaceholder.typicode.com/users/' + params.id,
1211
)
12+
if (!res.ok) {
13+
throw new Error('Failed to fetch user')
14+
}
15+
16+
const user = (await res.json()) as User
1317

1418
return json({
15-
id: res.data.id,
16-
name: res.data.name,
17-
email: res.data.email,
19+
id: user.id,
20+
name: user.name,
21+
email: user.email,
1822
})
1923
} catch (e) {
2024
console.error(e)

examples/react/start-basic/src/routes/api/users.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { json } from '@tanstack/react-start'
22
import { createAPIFileRoute } from '@tanstack/react-start/api'
3-
import axios from 'redaxios'
43
import type { User } from '../../utils/users'
54

65
export const APIRoute = createAPIFileRoute('/api/users')({
76
GET: async ({ request }) => {
87
console.info('Fetching users... @', request.url)
9-
const res = await axios.get<Array<User>>(
10-
'https://jsonplaceholder.typicode.com/users',
11-
)
8+
const res = await fetch('https://jsonplaceholder.typicode.com/users')
9+
if (!res.ok) {
10+
throw new Error('Failed to fetch users')
11+
}
1212

13-
const list = res.data.slice(0, 10)
13+
const data = (await res.json()) as Array<User>
14+
15+
const list = data.slice(0, 10)
1416

1517
return json(list.map((u) => ({ id: u.id, name: u.name, email: u.email })))
1618
},

examples/react/start-basic/src/routes/users.$userId.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import { createFileRoute } from '@tanstack/react-router'
2-
import axios from 'redaxios'
32
import type { User } from '~/utils/users'
43
import { DEPLOY_URL } from '~/utils/users'
54
import { NotFound } from '~/components/NotFound'
65
import { UserErrorComponent } from '~/components/UserError'
76

87
export const Route = createFileRoute('/users/$userId')({
98
loader: async ({ params: { userId } }) => {
10-
return await axios
11-
.get<User>(DEPLOY_URL + '/api/users/' + userId)
12-
.then((r) => r.data)
13-
.catch(() => {
14-
throw new Error('Failed to fetch user')
15-
})
9+
try {
10+
const res = await fetch(DEPLOY_URL + '/api/users/' + userId)
11+
if (!res.ok) {
12+
throw new Error('Unexpected status code')
13+
}
14+
15+
const data = (await res.json()) as User
16+
17+
return data
18+
} catch {
19+
throw new Error('Failed to fetch user')
20+
}
1621
},
1722
errorComponent: UserErrorComponent,
1823
component: UserComponent,

examples/react/start-basic/src/routes/users.route.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
2-
import axios from 'redaxios'
32
import { DEPLOY_URL } from '../utils/users'
43
import type { User } from '../utils/users'
54

65
export const Route = createFileRoute('/users')({
76
loader: async () => {
8-
return await axios
9-
.get<Array<User>>(DEPLOY_URL + '/api/users')
10-
.then((r) => r.data)
11-
.catch(() => {
12-
throw new Error('Failed to fetch users')
13-
})
7+
try {
8+
const res = await fetch(DEPLOY_URL + '/api/users')
9+
if (!res.ok) {
10+
throw new Error('Unexpected status code')
11+
}
12+
13+
const data = (await res.json()) as Array<User>
14+
15+
return data
16+
} catch {
17+
throw new Error('Failed to fetch users')
18+
}
1419
},
1520
component: UsersLayoutComponent,
1621
})
Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { notFound } from '@tanstack/react-router'
22
import { createServerFn } from '@tanstack/react-start'
3-
import axios from 'redaxios'
43

54
export type PostType = {
65
id: string
@@ -12,25 +11,32 @@ export const fetchPost = createServerFn({ method: 'GET' })
1211
.validator((d: string) => d)
1312
.handler(async ({ data }) => {
1413
console.info(`Fetching post with id ${data}...`)
15-
const post = await axios
16-
.get<PostType>(`https://jsonplaceholder.typicode.com/posts/${data}`)
17-
.then((r) => r.data)
18-
.catch((err) => {
19-
console.error(err)
20-
if (err.status === 404) {
21-
throw notFound()
22-
}
23-
throw err
24-
})
14+
const res = await fetch(
15+
`https://jsonplaceholder.typicode.com/posts/${data}`,
16+
)
17+
if (!res.ok) {
18+
if (res.status === 404) {
19+
throw notFound()
20+
}
21+
22+
throw new Error('Failed to fetch post')
23+
}
24+
25+
const post = (await res.json()) as PostType
2526

2627
return post
2728
})
2829

2930
export const fetchPosts = createServerFn({ method: 'GET' }).handler(
3031
async () => {
3132
console.info('Fetching posts...')
32-
return axios
33-
.get<Array<PostType>>('https://jsonplaceholder.typicode.com/posts')
34-
.then((r) => r.data.slice(0, 10))
33+
const res = await fetch('https://jsonplaceholder.typicode.com/posts')
34+
if (!res.ok) {
35+
throw new Error('Failed to fetch posts')
36+
}
37+
38+
const posts = (await res.json()) as Array<PostType>
39+
40+
return posts
3541
},
3642
)

examples/react/start-clerk-basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@clerk/tanstack-react-start": "0.12.0",
1313
"@tanstack/react-router": "^1.116.0",
1414
"@tanstack/react-router-devtools": "^1.116.0",
15-
"@tanstack/react-start": "^1.116.1",
15+
"@tanstack/react-start": "^1.116.2",
1616
"react": "^19.0.0",
1717
"react-dom": "^19.0.0",
1818
"redaxios": "^0.5.1",

examples/react/start-convex-trellaux/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@tanstack/react-router": "^1.116.0",
1818
"@tanstack/react-router-with-query": "^1.116.0",
1919
"@tanstack/react-router-devtools": "^1.116.0",
20-
"@tanstack/react-start": "^1.116.1",
20+
"@tanstack/react-start": "^1.116.2",
2121
"concurrently": "^8.2.2",
2222
"convex": "^1.19.0",
2323
"ky": "^1.7.4",

0 commit comments

Comments
 (0)