Skip to content

Commit

Permalink
Merge branch 'main' into link_exactOptionalPropertyTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanCassiere committed Sep 20, 2024
2 parents 689c865 + 84dbdd8 commit 7d892ac
Show file tree
Hide file tree
Showing 778 changed files with 44,038 additions and 14,095 deletions.
10 changes: 10 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ body:
- `router` Discussions tab: https://github.com/tanstack/router/discussions
The more information you fill in, the better the community can help you.
- type: dropdown
id: project
attributes:
label: Which project does this relate to?
description: If you are unsure, please leave this as "Router".
options:
- Router
- Start
validations:
required: true
- type: textarea
id: description
attributes:
Expand Down
1 change: 1 addition & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"typescript52",
"typescript53",
"typescript54",
"typescript55",
"unplugin",
"use-sync-external-store",
"waku"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Setup Tools
uses: tanstack/config/.github/setup@main
- name: Get base and head commits for `nx affected`
uses: nrwl/nx-set-shas@v4.0.6
uses: nrwl/nx-set-shas@v4.1.0
with:
main-branch-name: main
- name: Run Checks
Expand Down
25 changes: 25 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@
"label": "File-Based Routing",
"to": "framework/react/guide/file-based-routing"
},
{
"label": "Virtual File Routes",
"to": "framework/react/guide/virtual-file-routes"
},
{
"label": "Code Based Routing",
"to": "framework/react/guide/code-based-routing"
Expand Down Expand Up @@ -214,6 +218,10 @@
{
"label": "Static Prerendering",
"to": "framework/react/start/static-prerendering"
},
{
"label": "Path Aliases",
"to": "framework/react/start/path-aliases"
}
]
}
Expand All @@ -234,6 +242,19 @@
}
]
},
{
"label": "ESLint",
"children": [
{
"label": "ESLint Plugin Router",
"to": "eslint/eslint-plugin-router"
},
{
"label": "Create Route Property Order",
"to": "eslint/create-route-property-order"
}
]
},
{
"label": "Router Examples",
"children": [],
Expand Down Expand Up @@ -344,6 +365,10 @@
"label": "Basic + DIY Auth",
"to": "framework/react/examples/start-basic-auth"
},
{
"label": "Basic + Supabase Auth",
"to": "framework/react/examples/start-supabase-basic"
},
{
"label": "Trellaux + Convex",
"to": "framework/react/examples/start-convex-trellaux"
Expand Down
57 changes: 57 additions & 0 deletions docs/eslint/create-route-property-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
id: create-route-property-order
title: Ensure correct order of inference sensitive properties for createRoute functions
---

For the following functions, the property order of the passed in object matters due to type inference:

- `createRoute`
- `createFileRoute`
- `createRootRoute`
- `createRootRouteWithContext`

The correct property order is as follows:

- `params`
- `validateSearch`
- `context`
- `beforeLoad`
- `loaderDeps`
- `loader`

All other properties are insensitive to the order as they do not depend on type inference.

## Rule Details

Examples of **incorrect** code for this rule:

```tsx
/* eslint "@tanstack/router/create-route-property-order": "warn" */
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/foo/bar/$id')({
loader: async ({context}) => {
await context.queryClient.ensureQueryData(getQueryOptions(context.hello)),
},
beforeLoad: () => ({hello: 'world'})
})
```

Examples of **correct** code for this rule:

```tsx
/* eslint "@tanstack/router/create-route-property-order": "warn" */
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/foo/bar/$id')({
beforeLoad: () => ({hello: 'world'}),
loader: async ({context}) => {
await context.queryClient.ensureQueryData(getQueryOptions(context.hello)),
}
})
```

## Attributes

- [x] ✅ Recommended
- [x] 🔧 Fixable
96 changes: 96 additions & 0 deletions docs/eslint/eslint-plugin-router.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
id: eslint-plugin-router
title: ESLint Plugin Router
---

TanStack Router comes with its own ESLint plugin. This plugin is used to enforce best practices and to help you avoid common mistakes.

## Installation

The plugin is a separate package that you need to install:

```bash
$ npm i -D @tanstack/eslint-plugin-router
```

or

```bash
$ pnpm add -D @tanstack/eslint-plugin-router
```

or

```bash
$ yarn add -D @tanstack/eslint-plugin-router
```

or

```bash
$ bun add -D @tanstack/eslint-plugin-router
```

## Flat Config (`eslint.config.js`)

### Recommended setup

To enable all of the recommended rules for our plugin, add the following config:

```js
import pluginRouter from '@tanstack/eslint-plugin-router'

export default [
...pluginRouter.configs['flat/recommended'],
// Any other config...
]
```

### Custom setup

Alternatively, you can load the plugin and configure only the rules you want to use:

```js
import pluginRouter from '@tanstack/eslint-plugin-router'

export default [
{
plugins: {
'@tanstack/router': pluginRouter,
},
rules: {
'@tanstack/router/create-route-property-order': 'error',
},
},
// Any other config...
]
```

## Legacy Config (`.eslintrc`)

### Recommended setup

To enable all of the recommended rules for our plugin, add `plugin:@tanstack/eslint-plugin-router/recommended` in extends:

```json
{
"extends": ["plugin:@tanstack/eslint-plugin-router/recommended"]
}
```

### Custom setup

Alternatively, add `@tanstack/eslint-plugin-router` to the plugins section, and configure the rules you want to use:

```json
{
"plugins": ["@tanstack/eslint-plugin-router"],
"rules": {
"@tanstack/router/create-route-property-order": "error"
}
}
```

## Rules

- [@tanstack/router/create-route-property-order](../create-route-property-order)
1 change: 1 addition & 0 deletions docs/framework/react/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Feature/Capability Key:
| Typesafe Routes || 🛑 | 🟡 |
| Code-based Routes ||| 🛑 |
| File-based Routes ||||
| Virtual/Programmatic File-based Routes ||| 🛑 |
| Router Loaders ||||
| SWR Loader Caching || 🛑 ||
| Route Prefetching ||||
Expand Down
6 changes: 6 additions & 0 deletions docs/framework/react/guide/code-based-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ const layoutBRoute = createRoute({
getParentRoute: () => layoutRoute,
path: 'layout-b',
})

const routeTree = rootRoute.addChildren([
// The layout route has no path, only an id
// So its children will be nested under the layout route
layoutRoute.addChildren([layoutARoute, layoutBRoute]),
])
```

Now both `/layout-a` and `/layout-b` will render the their contents inside of the `LayoutComponent`:
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/guide/external-data-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export function createRouter() {
// On the client, hydrate the loader client with the data
// we dehydrated on the server
hydrate: (dehydrated) => {
hydrate(client, dehydrated.queryClientState)
hydrate(queryClient, dehydrated.queryClientState)
},
// Optionally, we can use `Wrap` to wrap our router in the loader client provider
Wrap: ({ children }) => {
Expand Down
48 changes: 46 additions & 2 deletions docs/framework/react/guide/file-based-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: File-Based Routing
---

Most of the TanStack Router documentation is written for file-based routing and is intended to help you understand in more detail how to configure file-based routing and the technical details behind how it works. While file-based routing is the preferred and recommended way to configure TanStack Router, you can also use [code-based routing](./code-based-routing) if you prefer.
Most of the TanStack Router documentation is written for file-based routing and is intended to help you understand in more detail how to configure file-based routing and the technical details behind how it works. While file-based routing is the preferred and recommended way to configure TanStack Router, you can also use [code-based routing](./code-based-routing.md) if you prefer.

## What is File-Based Routing?

Expand Down Expand Up @@ -87,6 +87,44 @@ It's extremely likely that a 100% directory or flat route structure won't be the

Both flat and directory routes can be mixed together to create a route tree that uses the best of both worlds where it makes sense.

## Virtual File Routes

> We'd like to thank the Remix team for [pioneering the concept of virtual file routes](https://www.youtube.com/watch?v=fjTX8hQTlEc&t=730s). We've taken inspiration from their work and adapted it to work with TanStack Router's existing file-based route-tree generation.
Virtual file routes are a powerful concept that allows you to build a route tree programmatically using code that references real files in your project. This can be useful if:

- You have an existing route organization that you want to keep.
- You want to customize the location of your route files.
- You want to completely override TanStack Router's file-based route generation and build your own convention.

Here's a quick example of using virtual file routes to map a route tree to a set of real files in your project:

```tsx
import {
rootRoute,
route,
index,
layout,
physical,
} from '@tanstack/virtual-file-routes'

const virtualRouteConfig = rootRoute('root.tsx', [
index('index.tsx'),
layout('layout.tsx', [
route('/dashboard', 'app/dashboard.tsx', [
index('app/dashboard-index.tsx'),
route('/invoices', 'app/dashboard-invoices.tsx', [
index('app/invoices-index.tsx'),
route('$id', 'app/invoice-detail.tsx'),
]),
]),
physical('/posts', 'posts'),
]),
])
```

For more information on how to configure virtual file routes, see the [Virtual File Routes](./virtual-file-routes.md) guide.

## Dynamic Path Params

Dynamic path params can be used in both flat and directory routes to create routes that can match a dynamic segment of the URL path. Dynamic path params are denoted by the `$` character in the filename:
Expand All @@ -96,7 +134,7 @@ Dynamic path params can be used in both flat and directory routes to create rout
| ... | ... | ... |
| ʦ `posts.$postId.tsx` | `/posts/$postId` | `<Root><Posts><Post><Post>` |

We'll learn more about dynamic path params in the [Path Params](./path-params) guide.
We'll learn more about dynamic path params in the [Path Params](./path-params.md) guide.

## Pathless Routes

Expand Down Expand Up @@ -133,8 +171,10 @@ File-based routing requires that you follow a few simple file naming conventions
- A folder that matches this pattern is treated as a **route group** which prevents this folder to be included in the route's URL path.
- **`index` Token**
- Routes segments ending with the `index` token (but before any file types) will be used to 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).
- **`.route.tsx` File Type**
- When using directories to organize your 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 at the route file for the `/blog/post` route.
This can be configured via the `routeToken` configuration option, see [options](#options).
- **`.lazy.tsx` File Type**
- The `lazy` suffix can be used to code-split components for a route. For example, `blog.post.lazy.tsx` will be used as the component for the `blog.post` route.

Expand Down Expand Up @@ -331,6 +371,10 @@ The following options are available for configuration via the `tsr.config.json`
- (Optional, **Defaults to `-`**) Route files and directories that start with this string will be ignored. By default this is set to `-` to allow for the use of directories to house related files that do not contain any route files.
- **`routeFileIgnorePattern`**
- (Optional) Ignore specific files and directories in the route directory. It can be used in regular expression format. For example, `.((css|const).ts)|test-page` will ignore files / directories with names containing `.css.ts`, `.const.ts` or `test-page`.
- **`indexToken`**
- (Optional, **Defaults to `'index'`**) allows to customize the `index` Token [file naming convention](#file-naming-conventions).
- **`routeToken`**
- (Optional, **Defaults to `'route'`**) allows to customize the `route` Token [file naming convention](#file-naming-conventions).
- **`routesDirectory`**
- (Required) The directory containing the routes relative to the cwd.
- **`generatedRouteTree`**
Expand Down
1 change: 1 addition & 0 deletions docs/framework/react/guide/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ It's also common to want to update a single search param without supplying any o
```tsx
const link = (
<Link
to="."
search={(prev) => ({
...prev,
page: prev.page + 1,
Expand Down
Loading

0 comments on commit 7d892ac

Please sign in to comment.