拥抱React+TS___2026-02-20

1. 环境准备 & 核心工具库 (Setup)

📦 必装依赖

# 1. 状态管理 & 数据请求 (替代 useEffect fetch)
npm install @tanstack/react-query

# 2. 类型生成 (开发依赖)
npm install -D openapi-typescript

# 3. 样式管理 (Tailwind 体系)
npm install class-variance-authority clsx tailwind-merge

# 4. 工具库
npm install lodash @types/lodash

# 5. 代码定位神器: https://inspector.fe-dev.cn/guide/start.html
npm install code-inspector-plugin -D

🛠 VS Code 效率插件

  1. Tailwind CSS IntelliSense: 智能提示,必装。
  2. Pretty TypeScript Errors: 让类型报错说人话。
  3. Inline Fold: (可选) 折叠 Tailwind 长字符串,眼不见心不烦。
  4. Cursor 编辑器: 推荐作为主力 IDE,替代手动维护上下文。

🔧 全局类型工具

src/types/global.d.ts 中加入,用于鼠标悬停时展开复杂类型:

export type Prettify<T> = {
  [K in keyof T]: T[K];
} & {};

2. 核心工作流 (The Golden Data Flow)

这是从后端到前端的单向数据流水线,核心思想是 “防腐层 (ACL)”“模型驱动”

Step 1: 后端定义 (FastAPI)

  • 后端使用 Pydantic 定义 Response Model
  • FastAPI 自动生成 /openapi.json

Step 2: 类型同步 (DTO Generation)

不要手写后端接口类型,在 package.json 配置脚本:

"scripts": {
  "gen-types": "npx openapi-typescript http://localhost:8000/openapi.json --output src/types/api.ts"
}
  • 操作:后端接口一变 -> 运行 npm run gen-types -> 前端报错 -> 修正。

Step 3: 数据清洗 (Model Class Pattern)

不要在组件中直接使用 DTO。 创建 Class 来清洗数据。

  • 位置src/models/User.ts
  • 作用:类型定义 + 数据转换 (int()函数) + 默认值处理。
import { components } from '@/types/api';

export class UserModel {
  id: string;
  fullName: string;
  avatar: string;

  // ✅ 构造函数即“转换器”
  constructor(data: components['schemas']['UserDTO']) {
    this.id = String(data.u_id);
    this.fullName = `${data.first_name} ${data.last_name}`;
    this.avatar = data.img_url || '/default.png';
  }
}

Step 4: 原子化 Hooks (Atomic Hooks)

不要写上帝 Hook,拆分为原子 Hook,并利用 React Query 缓存。

  • 位置src/hooks/useUser.ts
export const useUser = (id: string) => {
  return useQuery({
    queryKey: ['user', id],
    queryFn: async () => {
      const res = await fetch(`/api/users/${id}`).then(r => r.json());
      return new UserModel(res); // ✨ 实例化
    }
  });
};

3. React Hooks 使用准则

Hook 核心原则 (Do’s & Don’ts) 开销
useState 只存最原始的数据。能算出来的绝不存 State。
useEffect 同步专用(DOM、Title)。❌ 严禁用于数据流转换(setA -> Effect -> setB)。 ⭐⭐
Computed 直接写在函数体内(return 之前)。最高效,每次渲染自动更新。
useRef 存数据但不触发渲染。用于 Timer、DOM 引用。 🆓 (免费)
useCallback 只用于:保持引用稳定(传给 Memo 子组件、作为 Effect 依赖)。 ⭐⭐ (有成本)
useMemo 只用于:昂贵计算(大数组遍历)。简单的拼接不要用。 ⭐⭐⭐

4. 样式工作流 (Styling with Tailwind)

选择 Tailwind CSS,并使用工程化手段解决“长字符串”和“主题”问题。

🎨 核心库:CVA (Class Variance Authority)

替代 LESS Mixin,像写配置一样写样式。

// components/ui/button.tsx
import { cva } from 'class-variance-authority';
import { cn } from '@/lib/utils'; // 用于合并 class

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md transition-colors", // 基础样式
  {
    variants: {
      variant: { // 变体
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        outline: "border border-input hover:bg-accent",
      },
      size: { // 尺寸
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
      },
    },
    defaultVariants: { variant: "default", size: "default" },
  }
);

// 使用:<button className={cn(buttonVariants({ variant: 'outline' }))} />

🌗 主题系统 (Theming)

不要用 LESS 变量,使用 CSS Variables + Tailwind Config

  1. globals.css: 定义 CSS 变量(支持运行时切换深色模式)。

    :root { --primary: 222.2 47.4% 11.2%; }
    .dark { --primary: 210 40% 98%; }
    
  2. tailwind.config.js: 绑定变量。

    theme: { extend: { colors: { primary: "hsl(var(--primary))" } } }
    
  3. 开发: 使用语义化 Class。

    <div class="bg-primary text-primary-foreground">...</div>
    

🚀 快速起步推荐

直接使用 shadcn/ui 初始化项目。它会自动配置好上述的 cvacn 工具函数以及主题变量系统。

npx shadcn-ui@latest init

5. 组件架构原则

就近原则 (Co-location)

  • Props 定义:直接写在组件文件里 (interface Props {})。
  • 页面状态:直接写在 page.tsx 里。
  • 全局类型:只有跨多个文件使用的 Model 才放 src/typessrc/models

ID 驱动开发 (ID-Driven)

  • Smart Component (业务组件):只接收 id (e.g., <UserAvatar userId="123" />)。

    • 内部自行调用 useUser(id)
    • 利用 React Query 自动去重和缓存,避免 Prop Drilling。
  • Dumb Component (UI 组件):只接收数据 (e.g., <Avatar src="..." />)。

    • 纯展示,不包含业务逻辑。