用途
React Start(@tanstack/react-start)提供 TanStack Start 在 React 下的绑定、项目配置与使用模式。该技能建立在 start-core 之上,建议先阅读 start-core 了解基础概念;React Server Components 相关模式参见 react-start/server-components。
它明确区别于 Next.js 或 Remix:这是完全不同的框架,API 也不相同。
主要能力
@tanstack/react-start 重新导出 @tanstack/start-client-core 的全部内容,并额外提供:
- useServerFn —— 在 React 组件中调用服务端函数的 Hook。
核心 API(createServerFn、createMiddleware、createStart、createIsomorphicFn、createServerOnlyFn、createClientOnlyFn)均可从 @tanstack/react-start 导入。
服务端工具(getRequest、getRequestHeader、setResponseHeader、setResponseHeaders、setResponseStatus)从 @tanstack/react-start/server 导入。
重要约束:所有代码默认是同构的,loader 在服务端和客户端都会运行;服务端专属逻辑需使用 createServerFn。类型完全推断,不要做类型转换或对已推断值添加类型注解。
使用方式
完整项目搭建步骤:
- 安装依赖:
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescript @types/react @types/react-dom
- package.json:
{
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"start": "node .output/server/index.mjs"
}
}
- tsconfig.json:
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true
}
}
- vite.config.ts:
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
tanstackStart(), // 必须放在 react() 之前
viteReact(),
],
})
- 路由工厂(src/router.tsx):
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
const router = createRouter({
routeTree,
scrollRestoration: true,
})
return router
}
- 根路由(src/routes/__root.tsx):
import type { ReactNode } from 'react'
import {
Outlet,
createRootRoute,
HeadContent,
Scripts,
} from '@tanstack/react-router'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My TanStack Start App' },
],
}),
component: RootComponent,
})
function RootComponent() {
return (
<RootDocument>
<Outlet />
</RootDocument>
)
}
function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
return (
<html>
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
)
}
- 索引路由(src/routes/index.tsx):
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
return 'Hello from TanStack Start!'
})
export const Route = createFileRoute('/')({
loader: () => getGreeting(),
component: HomePage,
})
function HomePage() {
const greeting = Route.useLoaderData()
return <h1>{greeting}</h1>
}
使用 useServerFn 在组件中调用服务端函数:
import { createServerFn, useServerFn } from '@tanstack/react-start'
const updatePost = createServerFn({ method: 'POST' })
.inputValidator((data: { id: string; title: string }) => data)
.handler(async ({ data }) => {
await db.posts.update(data.id, { title: data.title })
return { success: true }
})
function EditPostForm({ postId }: { postId: string }) {
const updatePostFn = useServerFn(updatePost)
const [title, setTitle] = useState('')
return (
<form
onSubmit={async (e) => {
e.preventDefault()
await updatePostFn({ data: { id: postId, title } })
}}
>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<button type="submit">Save</button>
</form>
)
}
全局 Start 配置(src/start.ts):
import { createStart, createMiddleware } from '@tanstack/react-start'
const requestLogger = createMiddleware().server(async ({ next, request }) => {
console.log(`${request.method} ${request.url}`)
return next()
})
export const startInstance = createStart(() => ({
requestMiddleware: [requestLogger],
}))
React 专属组件
@tanstack/react-router 的路由组件都可在 Start 中使用:
- RouterProvider —— Start 中不需要(自动处理)
- Outlet —— 渲染匹配的子路由
- Link —— 类型安全导航
- Navigate —— 声明式重定向
- HeadContent —— 渲染 head 标签(必须位于 head 内)
- Scripts —— 渲染 body 脚本(必须位于 body 内)
- Await —— 配合 Suspense 渲染延迟数据
- ClientOnly —— 仅在 hydration 后渲染子节点
- CatchBoundary —— 错误边界
Hooks 参考:useRouter()、useRouterState()、useNavigate()、useSearch({ from })、useParams({ from })、useLoaderData({ from })、useMatch({ from })、useRouteContext({ from }),以及路由文件内推荐的 Route.useLoaderData() 和 Route.useSearch()。
常见错误
-
关键:从错误的包导入。createServerFn 应来自 @tanstack/react-start,而不是 @tanstack/react-router;路由 API(createFileRoute、Link)来自 @tanstack/react-router(Start 也重新导出)。
-
高:在 beforeLoad 或 loader 中使用 React Hook。它们不是 React 组件,状态应通过路由上下文传递。
-
高:遗漏 Scripts 组件。根路由 body 中缺少 <Scripts /> 会导致客户端 JavaScript 不加载、应用无法 hydration。
适用场景
需要使用 React 构建 TanStack Start 应用、配置项目结构、定义服务端函数与在组件中调用、配置全局 Start 中间件的场景。
限制
资料未提供该技能的安装方式、收费、价格或平台限制等信息。