Next.js 组件开发最佳实践文档(TypeScript 版)

1. 项目结构与组件规范

文件组织

bash 复制代码
/src  
├── components  
│   ├── ui          # 基础 UI 组件(无状态)  
│   │   └── Button.tsx  
│   └── features     # 业务组件(含状态与逻辑)  
│       └── UserList  
│           ├── UserList.tsx      # 主组件  
│           ├── useUserList.ts    # 自定义 Hook(状态与逻辑)  
│           └── types.ts          # 类型定义  

原则

基础 UI 组件 :保持无状态,仅接收 props,如按钮、输入框等。

业务组件:分离为 UI 层、状态层、逻辑层,通过自定义 Hook 管理副作用(如 API 调用)。


2. 组件设计原则

单一职责

• 每个组件仅解决一个核心问题(如展示、表单提交、数据加载)。

反例:一个组件同时处理数据请求、渲染和状态修改。

可复用性

• 通过 props 传递配置,避免硬编码逻辑。例如:

tsx 复制代码
type ButtonProps = {  
  variant?: "primary" | "secondary";  
  onClick: () => void;  
};  

3. TypeScript 集成规范

类型定义

• 使用 interfacetype 明确定义 propsstate

typescript 复制代码
// types.ts  
export interface User {  
  id: string;  
  name: string;  
  email: string;  
}  

export type UserListProps = {  
  initialUsers: User[];  
};  

组件类型注解

tsx 复制代码
import { FC } from "react";  

const UserList: FC<UserListProps> = ({ initialUsers }) => {  
  // ...  
};  

配置校验

• 使用 zod 验证 API 响应格式:

typescript 复制代码
import { z } from "zod";  

const UserSchema = z.object({  
  id: z.string(),  
  name: z.string().min(2),  
});  

4. UI 与状态分离实现

状态管理方案

轻量级场景 :使用 useState/useReducer(组件内状态)。

跨组件共享 :采用 ZustandContext API(全局状态)。

状态与 UI 分离示例

typescript 复制代码
// useUserList.ts  
import { useState } from "react";  

export const useUserList = (initialUsers: User[]) => {  
  const [users, setUsers] = useState<User[]>(initialUsers);  

  const addUser = (user: User) => {  
    setUsers([...users, user]);  
  };  

  return { users, addUser };  
};  

5. 操作逻辑解耦

副作用处理

• 将 API 调用、事件处理等逻辑封装为独立函数或服务层:

typescript 复制代码
// api/user.ts  
export const fetchUsers = async (): Promise<User[]> => {  
  const response = await fetch("/api/users");  
  return UserSchema.array().parse(response.data);  
};  

自定义 Hook 整合

typescript 复制代码
// useUserList.ts  
import { useEffect } from "react";  

export const useUserList = () => {  
  const [users, setUsers] = useState<User[]>([]);  

  useEffect(() => {  
    const loadData = async () => {  
      const data = await fetchUsers();  
      setUsers(data);  
    };  
    loadData();  
  }, []);  

  return { users };  
};  

6. 示例组件演示

用户列表组件(完整实现)

tsx 复制代码
// UserList.tsx  
import { FC } from "react";  
import { useUserList } from "./useUserList";  
import { User, UserListProps } from "./types";  
import Button from "@/components/ui/Button";  

const UserList: FC<UserListProps> = ({ initialUsers }) => {  
  const { users, addUser } = useUserList(initialUsers);  

  return (  
    <div>  
      <ul>  
        {users.map((user) => (  
          <li key={user.id}>{user.name}</li>  
        ))}  
      </ul>  
      <Button  
        variant="primary"  
        onClick={() => addUser({ id: "1", name: "New User" })}  
      >  
        添加用户  
      </Button>  
    </div>  
  );  
};  
相关推荐
某人辛木8 分钟前
Web自动化测试
前端·python·pycharm·pytest
Kagol44 分钟前
Superpowers GSD gstack AgentSkills深度测评
前端·人工智能
excel2 小时前
JavaScript 字符串与模板字面量:从表象到本质理解
前端
京东云开发者2 小时前
当AI成为导演-如何用AI创作动漫短剧
前端
李白的天不白2 小时前
使用 SmartAdmin 进行前后端开发
java·前端
乘风gg3 小时前
🤡PUA AI Coding 工具 的 10 条终极语录
前端·ai编程·claude
学Linux的语莫3 小时前
Vue 3 入门教程
前端·javascript·vue.js
怕浪猫3 小时前
第一章、Chrome DevTools Protocol (CDP) 详解
前端·javascript·chrome
kyriewen3 小时前
从本地到生产:迁移到 GitHub Actions 自动化 CI/CD,总结了这 5 个坑
前端·github·自动化运维
雨季mo浅忆4 小时前
首个Vue3项目边写边学边记
前端·vue3