TanStack 工具套件是一个既引人注目又现代的技术栈,它让开发者能够构建功能强大的全栈应用程序。该套件由 Vinxi 驱动,Vinxi 是一个 JavaScript SDK,可以使用 Vite 构建全栈应用,以便可以部署到任何 JavaScript 可运行的地方。该套件为前端开发者提供了一流的开发体验,同时集成了丰富的后端专业知识,因此,你将获得前后端的最佳结合。
在2025年,TanStack Start可能会与Astro、Next.js和Remix一起非常流行,用于构建React应用程序。今天,我们将了解TanStack套件中最常用的工具的基础,并看看它们如何帮助构建2025年的现代React应用程序。
我们将要探讨的工具有,包括:
搭建 TanStack Start 和 TanStack Router 项目好的,现在让我们开始设置我们的 React 项目,我们从 TanStack Start 开始。首先,在你的电脑上找到一个目录,比如桌面,然后使用这个脚本来设置项目:
mkdir tanstack-project
cd tanstack-project
npm create @tanstack/router@latest --legacy-peer-deps
全屏模式 退出全屏
使用此脚本,我们会创建一个名为 tanstack-project
的项目文件夹,并安装所需的软件包。
截至目前为止,TanStack Router 需要 React v18.3.1,所以如果你安装了更新版本,控制台可能会报错。最简单的解决办法是使用 --legacy-peer-deps
标志,这可以忽略由互相依赖的包引起的冲突。对于简单的测试来说这样做是可以的;而在实际使用中,建议使用更好的解决方法。
参考项目设置指南,我用的是下面这种配置:
- 项目名称: my-router-app
- 打包工具: Vite
- IDE: cursor
要运行你的应用程序,请确保你在项目文件夹里,然后运行下面的命令。
运行 npm run dev
来启动开发模式
全屏/退出全屏
你现在应该已经看到默认的 TanStack Router 主页,该主页带有首页和关于页面的路由。
案例图片:TanStack 官方首页
使用 TanStack Query 来管理状态我们现在有了应用程序的全局状态管理已经到位,接下来需要启动并运行TanStack Query。我们先安装所需的依赖项,运行下面的命令:
运行命令 npm install @tanstack/react-query @tanstack/react-query-devtools
来安装这两个包。
点击这里进入全屏,点击这里退出全屏
通过这些命令,我们现在能够访问我们应用程序的全局状态。
接下来,我们使用免费的JSONPlaceHolder API做一个简单的博客项目。好消息是,我们只需要修改两个文件就可以让这个项目跑起来,其中第一个步骤是将src/main.tsx
文件里的所有代码替换成下面的新代码。
import React from 'react' // 导入React库
import ReactDOM from 'react-dom/client' // 导入React的DOM渲染模块
import { RouterProvider, createRouter } from '@tanstack/react-router' // 导入路由提供者和创建路由的函数
import { routeTree } from './routeTree.gen' // 导入路由树
import {
QueryClient,
QueryClientProvider
} from '@tanstack/react-query' // 导入查询客户端和查询客户端提供者
import { ReactQueryDevtools } from '@tanstack/react-query-devtools' // 导入React查询工具调试组件
// 创建一个新的查询客户端,并设置默认选项
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 缓存数据过期时间
gcTime: 1000 * 60 * 60, // 清理缓存的时间
},
},
})
// 创建一个新的路由器实例
const router = createRouter({
routeTree,
defaultPreload: 'intent',
})
// 声明模块,用于自定义路由
declare module '@tanstack/react-router' {
interface Register { // 注册接口
router: typeof router // 路由器对象
}
}
// 获取ID为'app'的DOM元素
const rootElement = document.getElementById('app')!
if (!rootElement.innerHTML) { // 如果rootElement内容为空
const root = ReactDOM.createRoot(rootElement) // 创建一个新的根实例
root.render( // 渲染根实例
<React.StrictMode>
<QueryClientProvider client={queryClient}> // 提供查询客户端
<RouterProvider router={router} /> // 提供路由
<ReactQueryDevtools initialIsOpen={false} /> // 初始化调试工具,初始状态为关闭
</QueryClientProvider>
</React.StrictMode>
)
}
点击全屏进入/退出
这段代码基本上配置了我们的 React Query 客户端,使其在整个应用程序中都可以使用。它还具有某些默认查询参数,使其功能更佳。
最后,让我们也这样做一下,替换和更新文件内的所有代码。
import * as React from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
interface Post {
id: number;
title: string;
body: string;
}
const fetchPosts = async (): Promise<Post[]> => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
if (!response.ok) {
throw new Error('网络响应出错')
}
return response.json()
}
export const Route = createFileRoute('/')({
component: HomeComponent,
})
function HomeComponent() {
const {
data: posts,
isLoading,
isError,
error
} = useQuery<Post[], Error>({
queryKey: ['posts'],
queryFn: fetchPosts,
})
if (isLoading) {
return <div>加载中...</div>
}
if (isError) {
return <div>错误: {error.message}</div>
}
return (
<div className="p-4">
<h3 className="text-2xl font-bold mb-4">欢迎来到首页!</h3>
<h4 className="text-xl mb-2">最新帖子:</h4>
<div className="space-y-4">
{posts?.slice(0, 5).map((post) => (
<div key={post.id} className="bg-gray-600 p-3 rounded">
<h5 className="font-semibold">{post.title}</h5>
<p>{post.body}</p>
</div>
))}
</div>
</div>
)
}
切换到全屏,退出全屏
这个文件创建了一个 fetchPosts
函数来从 JSONPlaceholder API 获取帖子内容,并且使用了 useQuery
钩子来获取数据、管理状态和显示数据。使用 Tailwind CSS 进行样式设置。
你现在应该有一个类似下面这个例子的设计。
创建一个 TanStack Table 来展示数据.在我们开始之前,需要安装@tanstack/react-table
,请使用下面的脚本来安装。
运行以下命令来安装@tanstack/react-table插件:
npm install @tanstack/react-table
全屏(进入/退出)
我们的项目已经设置好了使用 TanStack 表格,我们现在可以开始处理这些文件了。我们需要创建一个名为 components
的文件夹,然后在这个文件夹内创建一个 DataTable.tsx
文件。
在下面的文件里加上这段代码:
将此代码添加到 components/DataTable.tsx
文件中:
import React, { useState } from 'react'
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
} from '@tanstack/react-table'
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
}
const defaultData: Person[] = [
{
firstName: 'John',
lastName: 'Doe',
age: 30,
visits: 5,
status: 'Active',
},
{
firstName: 'Jane',
lastName: 'Smith',
age: 25,
visits: 3,
status: 'Inactive',
},
]
const defaultColumns: ColumnDef<Person>[] = [
{
accessorKey: 'firstName',
header: 'First Name',
cell: (info) => info.getValue(),
},
{
accessorKey: 'lastName',
header: 'Last Name',
cell: (info) => info.getValue(),
},
{
accessorKey: 'age',
header: 'Age',
cell: (info) => info.getValue(),
},
{
accessorKey: 'visits',
header: 'Visits',
cell: (info) => info.getValue(),
},
{
accessorKey: 'status',
header: 'Status',
cell: (info) => info.getValue(),
},
]
export function DataTable() {
const [data] = useState(() => [...defaultData])
const [columns] = useState<ColumnDef<Person>[]>(() => [...defaultColumns])
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<div className="p-2">
<table className="w-full border-collapse border border-gray-300">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th
key={header.id}
className="border border-gray-300 p-2 bg-gray-600"
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id} className="hover:bg-gray-800">
{row.getVisibleCells().map((cell) => (
<td
key={cell.id}
className="border border-gray-300 p-2"
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}
全屏显示 退出全屏
在这份文件中,我们创建了一个用户对象的数组,然后将其输出至使用 TanStack 库创建的新表中。
最后修改 routes/about.tsx
文件如下所示:
import * as React from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { DataTable } from '../components/DataTable'
export const Route = createFileRoute('/about')({
component: AboutComponent,
})
function AboutComponent() {
return (
<div className="p-2">
<h3>用户列表</h3>
<DataTable />
</div>
)
}
进入全屏 退出全屏
这段代码更新了关于我们页面的用户新标题,并将新的数据表添加到页面上。您的关于我们页面现在应该有一个类似的表格,如下所示:
为操作行为添加 TanStack Form最后一步,让我们在关于我们页面上添加一个表单,以完成我们的应用。就像我们之前所做的那样,我们首先需要将所需的包添加到我们的应用中。
使用此脚本来安装它们
在终端中运行以下命令来安装所需的包:
npm install @tanstack/react-form zod
进入全屏,退出全屏
我们使用了 TanStack 表单和 Zod 进行表单验证。
好的,我们现在需要做的就是将这个新的代码添加到我们的 routes/about.tsx
文件中,这个新代码中有我们的表单,我们的应用就完成了。
import * as React from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { DataTable } from '../components/DataTable'
import { useForm } from '@tanstack/react-form'
import { z } from 'zod'
const formSchema = z.object({
firstName: z.string().min(2, '名字至少需要两个字符'),
lastName: z.string().min(2, '姓氏至少需要两个字符'),
age: z.coerce.number().min(0, '年龄必须是非负数'),
})
type FormValues = z.infer<typeof formSchema>
export const Route = createFileRoute('/about')({
component: AboutComponent,
})
function AboutComponent() {
const [errors, setErrors] = React.useState<Record<string, string>>({})
const [formState, setFormState] = React.useState<FormValues>({
firstName: '',
lastName: '',
age: 0,
})
const form = useForm<FormValues>({
defaultValues: formState,
onSubmit: async ({ value }) => {
try {
const validatedData = formSchema.parse(value)
console.log('表单已提交:', validatedData)
setErrors({})
setFormState(validatedData)
} catch (err) {
if (err instanceof z.ZodError) {
const newErrors: Record<string, string> = {}
err.errors.forEach((error) => {
if (error.path[0]) {
newErrors[error.path[0] as string] = error.message
}
})
setErrors(newErrors)
}
}
},
})
const validateField = (field: keyof FormValues, value: string | number) => {
try {
formSchema.shape[field].parse(value)
setErrors(prev => ({ ...prev, [field]: '' }))
} catch (err) {
if (err instanceof z.ZodError) {
setErrors(prev => ({ ...prev, [field]: err.errors[0].message }))
}
}
}
return (
<div className="p-2 max-w-md mx-auto">
<h3 className="text-2xl mb-4">用户信息</h3>
<DataTable />
<h3 className="text-2xl mt-6 mb-4">用户注册表单</h3>
<form
onSubmit={(e) => {
e.preventDefault()
e.stopPropagation()
void form.handleSubmit()
}}
className="space-y-4"
>
<div>
<label htmlFor="firstName" className="block mb-2">名</label>
<input
id="firstName"
type="text"
value={form.state.values.firstName}
onChange={(e) => {
const value = e.target.value
form.setFieldValue('firstName', value)
validateField('firstName', value)
}}
className="w-full p-2 border rounded"
/>
{errors.firstName && (
<p className="text-red-500 text-sm mt-1">
{errors.firstName}
</p>
)}
</div>
<div>
<label htmlFor="lastName" className="block mb-2">姓</label>
<input
id="lastName"
type="text"
value={form.state.values.lastName}
onChange={(e) => {
const value = e.target.value
form.setFieldValue('lastName', value)
validateField('lastName', value)
}}
className="w-full p-2 border rounded"
/>
{errors.lastName && (
<p className="text-red-500 text-sm mt-1">
{errors.lastName}
</p>
)}
</div>
<div>
<label htmlFor="age" className="block mb-2">年龄</label>
<input
id="age"
type="number"
value={form.state.values.age}
onChange={(e) => {
const value = Number(e.target.value)
form.setFieldValue('age', value)
validateField('age', value)
}}
className="w-full p-2 border rounded"
/>
{errors.age && (
<p className="text-red-500 text-sm mt-1">
{errors.age}
</p>
)}
</div>
<button
type="submit"
className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
>
保存并提交
</button>
</form>
<div className="mt-6 p-4 bg-gray-600 rounded">
<h3 className="text-xl mb-2">当前表单信息</h3>
<pre className="bg-slate-200 p-2 rounded text-black">
{JSON.stringify(formState, null, 2)}
</pre>
</div>
</div>
)
}
全屏模式 退出全屏
这段代码将在我们的关于页面上添加一个用户注册表,该表还具备验证功能。表单会将数据展示在页面上。请看下面的例子,您的关于页面应该看起来一样。
查看图片
最后说一下TanStack 工具套件可用于构建非常复杂的应用程序。多个工具甚至可以集成并用于其他框架,例如 Astro、Next.js 和 Remix。结合使用时,它们可以为您的项目提供全方位解决方案。今天,我们介绍了路由、状态管理和表格及表单构建的基础知识。我强烈建议您阅读 TanStack 官方文档,因为我们只是浅尝辄止。还有很多可以探索和实现的内容,文档涵盖了所有内容。
TanStack 工具套件还包括 TanStack Virtual,该库用于创建可滚动元素,TanStack Ranger 用于构建多范围滑块组件,TanStack Store 提供更强大的状态管理功能,以及 TanStack Config,用于配置和发布 JavaScript 包。凭借这种多功能性,TanStack 工具套件可以轻松实现高性能和功能丰富的 React 应用程序开发,在 2025 年。
此处省略部分内容
跟紧科技、编程、效率和人工智能的最新动态如果你喜欢这些文章,就来关注我,在我的社交媒体上(链接),我会分享与这些话题相关的各种内容 🔥
共同学习,写下你的评论
评论加载中...
作者其他优质文章