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>  
  );  
};  
相关推荐
qq_332539451 分钟前
React 前端框架推荐
前端·react.js·前端框架
拉不动的猪19 分钟前
刷刷题34(uniapp中级实际项目问题-1)
前端·vue.js·面试
奔跑的露西ly1 小时前
【HarmonyOS NEXT】实现文字环绕动态文本效果
前端·javascript·html·harmonyos
刺客-Andy2 小时前
React Vue 项开发中组件封装原则及注意事项
前端·vue.js·react.js
marzdata_lily3 小时前
从零到上线!7天搭建高并发体育比分网站全记录(附Java+Vue开源代码)
前端·后端
小君3 小时前
让 Cursor 更加聪明
前端·人工智能·后端
顾林海3 小时前
Flutter Dart 异常处理全面解析
android·前端·flutter
残轩3 小时前
JavaScript/TypeScript异步任务并发实用指南
前端·javascript·typescript
用户88442839014253 小时前
xterm + socket.io 实现 Web Terminal
前端