# SaaS项目自定义钩子使用文档

## 简介

本文档介绍了SaaS项目中的自定义React钩子(Custom Hooks)，这些钩子封装了常用的状态管理逻辑，使组件代码更加简洁、可读和可维护。

## 目录结构

```
src/
├── hooks/
│   ├── index.ts         # 统一导出所有钩子
│   ├── useUser.ts       # 用户相关钩子
│   └── useSettings.ts   # 设置相关钩子
└── store/
    ├── userStore.ts     # 用户状态管理
    └── settingStore.ts  # 设置状态管理
```

## 安装和导入

钩子已集成到项目中，无需额外安装。使用时只需从hooks目录导入：

```tsx
// 导入单个钩子
import { useTheme } from '@/hooks';

// 或导入多个钩子
import { useTheme, useAuth, useUserProfile } from '@/hooks';
```

## 用户相关钩子

### useUserInfo

获取当前登录用户的基本信息。

```tsx
import { useUserInfo } from '@/hooks';

function UserInfoComponent() {
  const userInfo = useUserInfo();
  
  return (
    <div>
      <p>用户名: {userInfo?.username}</p>
      <p>邮箱: {userInfo?.email}</p>
    </div>
  );
}
```

### useUserProfile

获取格式化后的用户信息，适用于UI显示。

```tsx
import { useUserProfile } from '@/hooks';

function ProfileComponent() {
  const profile = useUserProfile();
  
  return (
    <div>
      <p>用户名: {profile.username}</p>
      <p>邮箱: {profile.email}</p>
      <p>电话: {profile.phone}</p>
      <p>角色: {profile.roleName}</p>
    </div>
  );
}
```

### useIsAdmin

检查当前用户是否为管理员。

```tsx
import { useIsAdmin } from '@/hooks';

function AdminSection() {
  const isAdmin = useIsAdmin();
  
  if (!isAdmin) {
    return <p>您没有访问此页面的权限</p>;
  }
  
  return <div>管理员面板内容</div>;
}
```

### useHasRole

检查当前用户是否拥有特定角色。

```tsx
import { useHasRole } from '@/hooks';

function RoleBasedComponent() {
  const hasRole = useHasRole();
  
  return (
    <div>
      {hasRole('editor') && <button>编辑内容</button>}
      {hasRole('admin') && <button>管理设置</button>}
    </div>
  );
}
```

### useAuth

管理用户登录状态和认证操作。

```tsx
import { useAuth } from '@/hooks';

function LoginComponent() {
  const { isAuthenticated, login, logout } = useAuth();
  
  const handleLogin = async () => {
    const response = await fetch('/api/login', { /* 登录请求 */ });
    const data = await response.json();
    
    if (data.success) {
      login(data.token, data.user);
    }
  };
  
  return (
    <div>
      {isAuthenticated ? (
        <button onClick={logout}>退出登录</button>
      ) : (
        <button onClick={handleLogin}>登录</button>
      )}
    </div>
  );
}
```

## 设置相关钩子

### useTheme

管理主题模式（亮色/暗色）和相关操作。

```tsx
import { useTheme } from '@/hooks';

function ThemeToggleComponent() {
  const { 
    themeMode,
    isDarkMode, 
    toggleThemeMode, 
    enableLightMode, 
    enableDarkMode 
  } = useTheme();
  
  return (
    <div>
      <p>当前主题: {themeMode}</p>
      <button onClick={toggleThemeMode}>
        切换至{isDarkMode ? '亮色' : '暗色'}主题
      </button>
      <button onClick={enableLightMode} disabled={!isDarkMode}>
        切换至亮色主题
      </button>
      <button onClick={enableDarkMode} disabled={isDarkMode}>
        切换至暗色主题
      </button>
    </div>
  );
}
```

### useApplyTheme

自动将当前主题应用到DOM。适用于自定义布局组件或页面。

```tsx
import { useApplyTheme } from '@/hooks';

function Layout({ children }) {
  // 将当前主题应用到DOM
  useApplyTheme();
  
  return (
    <div className="layout">
      {children}
    </div>
  );
}
```

### useSettings

获取所有系统设置。

```tsx
import { useSettings } from '@/hooks';

function SettingsComponent() {
  const settings = useSettings();
  
  return (
    <div>
      <p>主题模式: {settings.themeMode}</p>
      {/* 其他设置项 */}
    </div>
  );
}
```

## 实际使用示例

下面是一个综合使用多个钩子的组件示例：

```tsx
import { 
  useTheme, 
  useApplyTheme, 
  useUserProfile, 
  useIsAdmin, 
  useAuth 
} from '@/hooks';

function DashboardPage() {
  // 应用主题到DOM
  useApplyTheme();
  
  // 获取主题状态和操作
  const { isDarkMode, toggleThemeMode } = useTheme();
  
  // 获取用户信息和权限
  const userProfile = useUserProfile();
  const isAdmin = useIsAdmin();
  const { isAuthenticated, logout } = useAuth();
  
  if (!isAuthenticated) {
    return <LoginRedirect />;
  }
  
  return (
    <div className="dashboard">
      <header>
        <div className="user-info">
          <p>欢迎, {userProfile.username}</p>
          <button onClick={logout}>退出登录</button>
        </div>
        <button onClick={toggleThemeMode}>
          切换至{isDarkMode ? '亮色' : '暗色'}主题
        </button>
      </header>
      
      <main>
        {/* 普通用户内容 */}
        <UserContent />
        
        {/* 仅管理员可见内容 */}
        {isAdmin && <AdminPanel />}
      </main>
    </div>
  );
}
```

## 测试页面

项目中包含一个专门的测试页面，用于演示各种钩子的使用方法：

- 路径: `/test/usehook`
- 源代码: `src/app/test/usehook/page.tsx`

在这个页面上可以测试以下功能：
- 主题切换
- 用户登录/登出
- 角色权限检查
- 用户信息显示

## 最佳实践

1. **避免重复导入基础store**：使用自定义钩子而不是直接导入store，减少对底层实现的依赖。

2. **优先使用语义化钩子**：例如使用`useIsAdmin()`而不是`useUserInfo().roleType === 'admin'`。

3. **组合使用多个钩子**：根据需要组合使用不同的钩子，构建复杂功能。

4. **使用useMemo和useCallback**：在性能敏感的场景中，确保不会导致不必要的重新渲染。

## 扩展自定义钩子

如需扩展现有钩子或添加新钩子，请遵循以下步骤：

1. 在适当的文件中添加新钩子（`useUser.ts`或`useSettings.ts`）
2. 在`hooks/index.ts`中导出新钩子
3. 确保包含适当的注释和类型定义
4. 遵循三级注释规范（文件头注释、模块级注释、关键代码行注释）

## 常见问题

**Q: 为什么推荐使用自定义钩子而不是直接使用store?**

A: 自定义钩子提供了更高级别的抽象，隐藏了状态管理的复杂性，使组件代码更加简洁和易于维护。同时，它们可以更轻松地进行单元测试。

**Q: 如何处理钩子之间的依赖关系?**

A: 当一个钩子需要依赖另一个钩子时，应在钩子内部导入并使用依赖的钩子，而不是在组件中手动管理这些依赖关系。

**Q: 如何确保钩子在正确的上下文中使用?**

A: React钩子只能在React函数组件或其他自定义钩子中使用。确保不在类组件、普通函数或条件语句中直接调用钩子。 