React
2026-03-28
新闻来源:网淘吧
围观:17
电脑广告
手机广告
React
生产级React工程能力。此技能将改变您构建React应用程序的方式——从组件架构到部署。
使用场景
- 构建React组件、页面或功能
- 实现状态管理(useState、Context、Zustand、TanStack Query)
- 使用React 19(服务器组件、use()、Actions)
- 优化性能(memo、lazy、Suspense)
- 调试渲染问题、无限循环、过时闭包
- 设置项目架构和文件夹结构
架构决策
在编写代码前,请做出以下决策:
| 决策项 | 选项 | 默认选择 |
|---|---|---|
| 渲染方式 | SPA / SSR / 静态生成 / 混合模式 | SSR(Next.js) |
| 状态管理(服务器端) | TanStack Query / SWR / use() | TanStack Query |
| 状态(客户端) | useState / Zustand / Jotai | 共享状态用 Zustand |
| 样式 | Tailwind / CSS Modules / styled | 首选 Tailwind |
| 表单 | React Hook Form + Zod / 原生表单 | 首选 RHF + Zod |
规则:服务器状态(API 数据)和客户端状态(UI 状态)是**不同**的。切勿混用。
组件规则
// ✅ The correct pattern
export function UserCard({ user, onEdit }: UserCardProps) {
// 1. Hooks first (always)
const [isOpen, setIsOpen] = useState(false)
// 2. Derived state (NO useEffect for this)
const fullName = `${user.firstName} ${user.lastName}`
// 3. Handlers
const handleEdit = useCallback(() => onEdit(user.id), [onEdit, user.id])
// 4. Early returns
if (!user) return null
// 5. JSX (max 50 lines)
return (...)
}
| 规则 | 原因 |
|---|---|
| 仅使用具名导出 | 重构安全,IDE 支持 |
| 导出 Props 接口 | 可复用,有文档说明 |
| JSX 最多 50 行 | 超过则提取 |
| 文件最多 300 行 | 拆分成组件 |
| Hook 放在顶部 | 遵循 React 规则 + 可预测性 |
状态管理
Is it from an API?
├─ YES → TanStack Query (NOT Redux, NOT Zustand)
└─ NO → Is it shared across components?
├─ YES → Zustand (simple) or Context (if rarely changes)
└─ NO → useState
TanStack Query(服务器状态)
// Query key factory — prevents key typos
export const userKeys = {
all: ['users'] as const,
detail: (id: string) => [...userKeys.all, id] as const,
}
export function useUser(id: string) {
return useQuery({
queryKey: userKeys.detail(id),
queryFn: () => fetchUser(id),
staleTime: 5 * 60 * 1000, // 5 min
})
}
Zustand(客户端状态)
// Thin stores, one concern each
export const useUIStore = create<UIState>()((set) => ({
sidebarOpen: true,
toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
}))
// ALWAYS use selectors — prevents unnecessary rerenders
const isOpen = useUIStore((s) => s.sidebarOpen)
React 19
服务器组件(Next.js App Router 中的默认设置)
// Server Component — runs on server, zero JS to client
async function ProductList() {
const products = await db.products.findMany() // Direct DB access
return <ul>{products.map(p => <ProductCard key={p.id} product={p} />)}</ul>
}
// Client Component — needs 'use client' directive
'use client'
function AddToCartButton({ productId }: { productId: string }) {
const [loading, setLoading] = useState(false)
return <button onClick={() => addToCart(productId)}>Add</button>
}
| 服务器组件 | 客户端组件 |
|---|---|
| async/await ✅ | useState ✅ |
| 直接数据库访问 ✅ | onClick ✅ |
| 无捆绑包大小 | 增加捆绑包大小 |
| useState ❌ | async ❌ |
use() Hook
// Read promises in render (with Suspense)
function Comments({ promise }: { promise: Promise<Comment[]> }) {
const comments = use(promise) // Suspends until resolved
return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>
}
useActionState(表单处理)
'use client'
async function submitAction(prev: State, formData: FormData) {
'use server'
// ... server logic
return { success: true }
}
function Form() {
const [state, action, pending] = useActionState(submitAction, {})
return (
<form action={action}>
<input name="email" disabled={pending} />
<button disabled={pending}>{pending ? 'Saving...' : 'Save'}</button>
{state.error && <p>{state.error}</p>}
</form>
)
}
性能
| 优先级 | 技术 | 影响 |
|---|---|---|
| P0 | 基于路由的代码分割 | 🔴 高 |
| P0 | 图像优化 (next/image) | 🔴 高 |
| P1 | 虚拟化长列表 (tanstack-virtual) | 🟡 中 |
| P1 | 对高开销操作进行防抖 | 🟡 中 |
| P2 | 对高开销组件使用 React.memo | 🟢 低-中 |
| P2 | 对高开销计算使用 useMemo | 🟢 低-中 |
React 编译器 (React 19+):自动记忆化。移除手动的 memo/useMemo/useCallback。
常见陷阱
渲染陷阱
// ❌ Renders "0" when count is 0
{count && <Component />}
// ✅ Explicit boolean
{count > 0 && <Component />}
// ❌ Mutating state — React won't detect
array.push(item)
setArray(array)
// ✅ New reference
setArray([...array, item])
// ❌ New key every render — destroys component
<Item key={Math.random()} />
// ✅ Stable key
<Item key={item.id} />
钩子陷阱
// ❌ useEffect cannot be async
useEffect(async () => { ... }, [])
// ✅ Define async inside
useEffect(() => {
async function load() { ... }
load()
}, [])
// ❌ Missing cleanup — memory leak
useEffect(() => {
const sub = subscribe()
}, [])
// ✅ Return cleanup
useEffect(() => {
const sub = subscribe()
return () => sub.unsubscribe()
}, [])
// ❌ Object in deps — triggers every render
useEffect(() => { ... }, [{ id: 1 }])
// ✅ Extract primitives or memoize
useEffect(() => { ... }, [id])
数据获取陷阱
// ❌ Sequential fetches — slow
const users = await fetchUsers()
const orders = await fetchOrders()
// ✅ Parallel
const [users, orders] = await Promise.all([fetchUsers(), fetchOrders()])
// ❌ Race condition — no abort
useEffect(() => {
fetch(url).then(setData)
}, [url])
// ✅ Abort controller
useEffect(() => {
const controller = new AbortController()
fetch(url, { signal: controller.signal }).then(setData)
return () => controller.abort()
}, [url])
需避免的 AI 错误
AI 助手在处理 React 时常犯的错误:
| 错误 | 正确模式 |
|---|---|
| useEffect用于派生状态 | 内联计算:const x = a + b |
| Redux用于API数据 | TanStack Query用于服务器状态 |
| 默认导出 | 命名导出:export function X |
| 动态列表中使用索引作为key | 稳定ID:key={item.id} |
| 在useEffect中获取数据 | TanStack Query或加载器模式 |
| 巨型组件(500+行) | 按50行JSX、300行文件拆分 |
| 没有错误边界 | 在应用、功能、组件级别添加 |
| 忽略TypeScript严格模式 | 启用strict: true,修复所有错误 |
快速参考
钩子
| 钩子 | 用途 |
|---|---|
| useState | 本地状态 |
| useEffect | 副作用(订阅、DOM操作) |
| useCallback | 稳定的函数引用 |
| useMemo | 昂贵的计算 |
| useRef | 可变引用、DOM访问 |
| use() | 读取Promise/上下文(React 19) |
| useActionState | 表单操作状态(React 19) |
| useOptimistic | 乐观UI(React 19) |
文件结构
src/
├── app/ # Routes (Next.js)
├── features/ # Feature modules
│ └── auth/
│ ├── components/ # Feature components
│ ├── hooks/ # Feature hooks
│ ├── api/ # API calls
│ └── index.ts # Public exports
├── shared/ # Cross-feature
│ ├── components/ui/ # Button, Input, etc.
│ └── hooks/ # useDebounce, etc.
└── providers/ # Context providers
设置
参见setup.md以进行首次配置。使用memory-template.md进行项目跟踪。
核心规则
- 服务器状态 ≠ 客户端状态— API数据放入TanStack Query,UI状态用useState/Zustand。绝不混用。
- 仅使用命名导出—
export function X而非export default。便于安全重构。 - 先集中,后提取— 状态始于使用处附近。仅在需要时提升。
- 勿用useEffect处理派生状态— 内联计算:
const total = items.reduce(...)。Effect用于处理副作用。 - 始终使用稳定键— 动态列表使用
item.id,绝不用index。 - JSX最多50行— 若更长,提取组件。每个文件最多300行。
- TypeScript严格模式:true— 禁用
任何,没有隐式空值。在编译时捕获错误。
相关技能
安装命令clawhub install <slug>如果用户确认:
- 前端设计终极版— 使用 React + Tailwind 构建完整用户界面
- TypeScript— TypeScript 模式与严格配置
- Next.js— Next.js 应用路由与部署
- 测试— 使用 Testing Library 测试 React 组件
反馈
- 如果觉得有用:
clawhub star react - 保持更新:
clawhub sync
文章底部电脑广告
手机广告位-内容正文底部


微信扫一扫,打赏作者吧~