在开始从 React Location 迁移的旅程之前,重要的是您对 TanStack Router 使用的 路由概念 和 设计决策 有很好的理解。
React Location 和 TanStack Router 在很大程度上共享相同的设计决策概念,但您应该注意一些关键差异。
在本指南中,我们将介绍将 React Location Basic 示例 使用基于文件的路由迁移到 TanStack Router 的过程,最终目标是拥有与原始示例相同的功能(样式和其他非路由相关代码将被省略)。
提示
要使用基于代码的方法来定义路由,您可以阅读基于代码的路由指南。
首先,我们需要安装 TanStack Router 的依赖项。
npm install @tanstack/react-router @tanstack/router-devtools
npm install @tanstack/react-router @tanstack/router-devtools
并删除 React Location 依赖项。
npm uninstall @tanstack/react-location @tanstack/react-location-devtools
npm uninstall @tanstack/react-location @tanstack/react-location-devtools
如果您的项目使用 Vite(或受支持的 bundler 之一),您可以使用 TanStack Router 插件来监视路由文件中的更改并自动更新路由配置。
Vite 插件的安装
npm install -D @tanstack/router-plugin
npm install -D @tanstack/router-plugin
并将其添加到您的 vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
export default defineConfig({
// ...
plugins: [TanStackRouterVite(), react()],
})
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
export default defineConfig({
// ...
plugins: [TanStackRouterVite(), react()],
})
但是,如果您的应用程序不使用 Vite,您可以使用我们的其他受支持的 bundler之一,或者您可以使用 @tanstack/router-cli 包来监视路由文件中的更改并自动更新路由配置。
在您的项目根目录中创建一个 tsr.config.json 文件,内容如下
{
"routesDirectory": "./src/routes",
"generatedRouteTree": "./src/routeTree.gen.ts"
}
{
"routesDirectory": "./src/routes",
"generatedRouteTree": "./src/routeTree.gen.ts"
}
您可以在此处找到 tsr.config.json 文件的完整选项列表。
在您的项目的 src 目录中创建一个 routes 目录。
mkdir src/routes
mkdir src/routes
// src/routes/__root.tsx
import { createRootRoute, Outlet, Link } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
export const Route = createRootRoute({
component: () => {
return (
<>
<div>
<Link to="/" activeOptions={{ exact: true }}>
Home
</Link>
<Link to="/posts">Posts</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
)
},
})
// src/routes/__root.tsx
import { createRootRoute, Outlet, Link } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
export const Route = createRootRoute({
component: () => {
return (
<>
<div>
<Link to="/" activeOptions={{ exact: true }}>
Home
</Link>
<Link to="/posts">Posts</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
)
},
})
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: Index,
})
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: Index,
})
您将需要将索引路由所需的任何相关组件和逻辑从 src/index.tsx 文件移动到 src/routes/index.tsx 文件。
// src/routes/posts.tsx
import { createFileRoute, Link, Outlet } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
component: Posts,
loader: async () => {
const posts = await fetchPosts()
return {
posts,
}
},
})
function Posts() {
const { posts } = Route.useLoaderData()
return (
<div>
<nav>
{posts.map((post) => (
<Link
key={post.id}
to={`/posts/$postId`}
params={{ postId: post.id }}
>
{post.title}
</Link>
))}
</nav>
<Outlet />
</div>
)
}
// src/routes/posts.tsx
import { createFileRoute, Link, Outlet } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
component: Posts,
loader: async () => {
const posts = await fetchPosts()
return {
posts,
}
},
})
function Posts() {
const { posts } = Route.useLoaderData()
return (
<div>
<nav>
{posts.map((post) => (
<Link
key={post.id}
to={`/posts/$postId`}
params={{ postId: post.id }}
>
{post.title}
</Link>
))}
</nav>
<Outlet />
</div>
)
}
您将需要将 posts 路由所需的任何相关组件和逻辑从 src/index.tsx 文件移动到 src/routes/posts.tsx 文件。
// src/routes/posts.index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/')({
component: PostsIndex,
})
// src/routes/posts.index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/')({
component: PostsIndex,
})
您将需要将 posts 索引路由所需的任何相关组件和逻辑从 src/index.tsx 文件移动到 src/routes/posts.index.tsx 文件。
// src/routes/posts.$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
component: PostsId,
loader: async ({ params: { postId } }) => {
const post = await fetchPost(postId)
return {
post,
}
},
})
function PostsId() {
const { post } = Route.useLoaderData()
// ...
}
// src/routes/posts.$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
component: PostsId,
loader: async ({ params: { postId } }) => {
const post = await fetchPost(postId)
return {
post,
}
},
})
function PostsId() {
const { post } = Route.useLoaderData()
// ...
}
您将需要将 posts id 路由所需的任何相关组件和逻辑从 src/index.tsx 文件移动到 src/routes/posts.$postId.tsx 文件。
如果您使用的是受支持的 bundler 之一,则在您运行开发脚本时将自动生成路由树。
如果您没有使用受支持的 bundler 之一,则可以通过运行以下命令来生成路由树
npx tsr generate
npx tsr generate
生成路由树后,您可以更新 src/index.tsx 文件以创建 router 实例并渲染它。
// src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { createRouter, RouterProvider } from '@tanstack/react-router'
// Import the generated route tree
import { routeTree } from './routeTree.gen'
// Create a new router instance
const router = createRouter({ routeTree })
// Register the router instance for type safety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
const domElementId = 'root' // Assuming you have a root element with the id 'root'
// Render the app
const rootElement = document.getElementById(domElementId)
if (!rootElement) {
throw new Error(`Element with id ${domElementId} not found`)
}
ReactDOM.createRoot(rootElement).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
)
// src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { createRouter, RouterProvider } from '@tanstack/react-router'
// Import the generated route tree
import { routeTree } from './routeTree.gen'
// Create a new router instance
const router = createRouter({ routeTree })
// Register the router instance for type safety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
const domElementId = 'root' // Assuming you have a root element with the id 'root'
// Render the app
const rootElement = document.getElementById(domElementId)
if (!rootElement) {
throw new Error(`Element with id ${domElementId} not found`)
}
ReactDOM.createRoot(rootElement).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
)
您现在应该已使用基于文件的路由成功地将您的应用程序从 React Location 迁移到 TanStack Router。
React Location 还有一些您可能在应用程序中使用的其他功能。以下是一些指南,可帮助您迁移这些功能
TanStack Router 还有一些您可能想要探索的更多功能
如果您遇到任何问题或有任何疑问,请随时在 TanStack Discord 中寻求帮助。
您的每周 JavaScript 新闻。每周一免费发送给超过 100,000 名开发人员。