# 🎣 React Hooks 使用指南

T-REX Passport SDK 现在提供官方的 React Hook 支持，让您能够轻松地在 React 应用中集成 Passport 功能！

## ✨ 特性

- 🔄 **自动状态管理** - 自动处理加载状态、错误处理和数据更新
- 🔗 **智能重连** - 自动监听钱包和网络变化
- ⚡ **轮询支持** - 可配置的数据轮询更新
- 🎯 **类型安全** - 完整的 TypeScript 支持
- 🧹 **自动清理** - 组件卸载时自动清理资源
- 📦 **可选依赖** - React 是可选的，不会影响非 React 用户

## 📦 安装

```bash
# 安装主包
npm install @keccak256-evg/passport-sdk

# 如果使用 React Hook，还需要安装 React（如果还没有的话）
npm install react
```

## 🚀 快速开始

### 1. useUnifiedPassportSDK - 主要 SDK Hook

```typescript
import { useUnifiedPassportSDK } from '@keccak256-evg/passport-sdk';

function MyComponent() {
  const { 
    sdk, 
    isInitializing, 
    error, 
    providerInfo 
  } = useUnifiedPassportSDK({
    chain: {
      id: 1962,
      name: 'T-Rex Testnet',
      rpcUrls: { default: { http: ['https://testnetrpc.trex.xyz'] } }
    },
    autoInitialize: true, // 自动初始化
    userAddress: userWalletAddress // 监听用户地址变化
  });

  if (isInitializing) return <div>初始化中...</div>;
  if (error) return <div>错误: {error.message}</div>;
  if (!sdk) return <div>请连接钱包</div>;

  return <div>SDK 已就绪！钱包类型: {providerInfo?.isMetaMask ? 'MetaMask' : '其他'}</div>;
}
```

### 2. useWalletPassport - 检查钱包 Passport

```typescript
import { useWalletPassport } from '@keccak256-evg/passport-sdk';

function PassportStatus({ sdk, userAddress }) {
  const { 
    hasPassport, 
    passportId, 
    passportAddress, 
    isLoading, 
    error,
    check 
  } = useWalletPassport({
    sdk,
    walletAddress: userAddress,
    autoCheck: true,
    pollingInterval: 30000 // 每30秒检查一次
  });

  if (isLoading) return <div>检查中...</div>;
  if (error) return <div>错误: {error.message} <button onClick={check}>重试</button></div>;

  return (
    <div>
      {hasPassport ? (
        <div>
          ✅ 您有 Passport！
          <p>ID: {passportId}</p>
          <p>地址: {passportAddress}</p>
        </div>
      ) : (
        <div>❌ 您还没有 Passport</div>
      )}
    </div>
  );
}
```

### 3. usePassportInfo - 获取 Passport 详细信息

```typescript
import { usePassportInfo } from '@keccak256-evg/passport-sdk';

function PassportDetails({ sdk, passportAddress }) {
  const { 
    passportInfo, 
    isLoading, 
    error, 
    refresh 
  } = usePassportInfo({
    sdk,
    passportAddress,
    autoFetch: true,
    pollingInterval: 60000 // 每分钟更新一次
  });

  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>错误: {error.message} <button onClick={refresh}>重新加载</button></div>;
  if (!passportInfo) return null;

  return (
    <div>
      <h3>Passport 详细信息</h3>
      <p>ID: {passportInfo.passportId}</p>
      <p>地址: {passportInfo.passportAddress}</p>
      <p>绑定钱包数量: {passportInfo.walletCount}</p>
      <div>
        <h4>绑定的钱包:</h4>
        {passportInfo.boundWallets.map((wallet, index) => (
          <p key={index}>{wallet}</p>
        ))}
      </div>
      <button onClick={refresh}>刷新</button>
    </div>
  );
}
```

## 🔧 Hook API 参考

### useUnifiedPassportSDK

**配置选项:**
```typescript
interface UseUnifiedPassportSDKConfig {
  chain: {
    id: number;
    name: string;
    rpcUrls: { default: { http: string[] } };
    nativeCurrency?: { name: string; symbol: string; decimals: number };
    blockExplorers?: { default: { name: string; url: string } };
  };
  env?: 'dev' | 'prod';
  registryAddress?: string;
  autoInitialize?: boolean; // 默认 true
  userAddress?: string; // 用于监听地址变化
}
```

**返回值:**
```typescript
interface UseUnifiedPassportSDKReturn {
  sdk: UnifiedPassportSDK | null;
  isInitializing: boolean;
  error: Error | null;
  initialize: () => Promise<void>;
  cleanup: () => void;
  providerInfo: {
    isMetaMask: boolean;
    isCoinbaseWallet: boolean;
    chainId?: string;
    selectedAddress?: string;
  } | null;
}
```

### useWalletPassport

**配置选项:**
```typescript
interface UseWalletPassportConfig {
  sdk: UnifiedPassportSDK | null;
  walletAddress?: Address;
  autoCheck?: boolean; // 默认 true
  pollingInterval?: number; // 0 表示不轮询
}
```

**返回值:**
```typescript
interface UseWalletPassportReturn {
  walletPassport: WalletPassportResult | null;
  isLoading: boolean;
  error: Error | null;
  check: () => Promise<void>;
  clear: () => void;
  // 便捷属性
  hasPassport: boolean;
  passportId?: number;
  passportAddress?: Address;
}
```

### usePassportInfo

**配置选项:**
```typescript
interface UsePassportInfoConfig {
  sdk: UnifiedPassportSDK | null;
  passportAddress?: Address;
  autoFetch?: boolean; // 默认 true
  pollingInterval?: number; // 0 表示不轮询
}
```

**返回值:**
```typescript
interface UsePassportInfoReturn {
  passportInfo: PassportInfo | null;
  isLoading: boolean;
  error: Error | null;
  refresh: () => Promise<void>;
  clear: () => void;
}
```

## 💡 最佳实践

### 1. 组合使用 Hooks

```typescript
function PassportDashboard({ userAddress }) {
  // 1. 初始化 SDK
  const { sdk, isInitializing, error } = useUnifiedPassportSDK({
    chain: tRexTestnetConfig,
    userAddress,
    autoInitialize: true
  });

  // 2. 检查钱包状态
  const { hasPassport, passportAddress } = useWalletPassport({
    sdk,
    walletAddress: userAddress,
    autoCheck: true
  });

  // 3. 获取详细信息（仅当有 Passport 时）
  const { passportInfo } = usePassportInfo({
    sdk,
    passportAddress: hasPassport ? passportAddress : undefined,
    autoFetch: true
  });

  // 渲染逻辑...
}
```

### 2. 自定义 Hook

```typescript
// 封装常用逻辑
function usePassportOperations(userAddress?: string) {
  const sdkResult = useUnifiedPassportSDK({
    chain: tRexTestnetConfig,
    userAddress,
    autoInitialize: true
  });

  const walletResult = useWalletPassport({
    sdk: sdkResult.sdk,
    walletAddress: userAddress,
    autoCheck: true
  });

  const createPassport = async () => {
    if (!sdkResult.sdk) throw new Error('SDK not ready');
    return await sdkResult.sdk.createPassport();
  };

  return {
    ...sdkResult,
    ...walletResult,
    createPassport,
    isReady: !!sdkResult.sdk && !sdkResult.isInitializing && !sdkResult.error
  };
}

// 使用自定义 Hook
function MyComponent({ userAddress }) {
  const { 
    isReady, 
    hasPassport, 
    createPassport, 
    isInitializing 
  } = usePassportOperations(userAddress);

  if (isInitializing) return <div>加载中...</div>;
  if (!isReady) return <div>SDK 未就绪</div>;

  return (
    <div>
      {hasPassport ? (
        <div>您已有 Passport</div>
      ) : (
        <button onClick={createPassport}>创建 Passport</button>
      )}
    </div>
  );
}
```

### 3. 错误处理

```typescript
function ErrorBoundaryComponent() {
  const { sdk, error, initialize } = useUnifiedPassportSDK({
    chain: tRexTestnetConfig,
    autoInitialize: true
  });

  // 全局错误处理
  React.useEffect(() => {
    if (error) {
      console.error('SDK Error:', error);
      // 可以发送到错误追踪服务
      // trackError(error);
    }
  }, [error]);

  if (error) {
    return (
      <div className="error-state">
        <h3>出错了 😞</h3>
        <p>{error.message}</p>
        <button onClick={initialize}>重试</button>
        <details>
          <summary>技术详情</summary>
          <pre>{error.stack}</pre>
        </details>
      </div>
    );
  }

  // 正常渲染...
}
```

### 4. 轮询控制

```typescript
function PassportMonitor({ userAddress }) {
  const [isMonitoring, setIsMonitoring] = useState(true);

  const { hasPassport, passportAddress } = useWalletPassport({
    sdk,
    walletAddress: userAddress,
    autoCheck: true,
    pollingInterval: isMonitoring ? 30000 : 0 // 根据状态控制轮询
  });

  return (
    <div>
      <label>
        <input 
          type="checkbox" 
          checked={isMonitoring}
          onChange={e => setIsMonitoring(e.target.checked)}
        />
        启用自动监控
      </label>
      {/* 其他内容... */}
    </div>
  );
}
```

## 🎨 样式建议

```css
/* 推荐的基础样式 */
.passport-dashboard {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.passport-dashboard.loading {
  text-align: center;
  opacity: 0.7;
}

.passport-dashboard.error {
  border: 2px solid #ff6b6b;
  border-radius: 8px;
  padding: 20px;
  background: #ffe0e0;
}

.provider-info {
  background: #f0f8ff;
  padding: 15px;
  border-radius: 8px;
  margin: 15px 0;
}

.wallet-passport {
  border: 1px solid #ddd;
  padding: 15px;
  border-radius: 8px;
  margin: 15px 0;
}

.has-passport {
  color: #4caf50;
}

.no-passport {
  color: #ff9800;
}

.actions {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.actions button {
  padding: 10px 15px;
  border: none;
  border-radius: 5px;
  background: #007bff;
  color: white;
  cursor: pointer;
}

.actions button:hover {
  background: #0056b3;
}
```

## 📱 完整示例

查看 [`examples/react-hooks-usage.tsx`](./examples/react-hooks-usage.tsx) 获取完整的使用示例，包括：

- 完整的 Passport 仪表板
- 错误处理和重试逻辑
- 自定义 Hook 封装
- 轮询和实时更新
- 样式和用户体验最佳实践

## ❓ 常见问题

### Q: Hook 是否支持服务端渲染 (SSR)？
A: 部分支持。Hook 会自动检测环境，在服务端不会尝试访问 `window` 对象，但 SDK 功能需要在客户端才能工作。

### Q: 如何处理网络切换？
A: Hook 会自动监听网络变化并在控制台输出警告。您可以通过 `providerInfo.chainId` 检查当前网络。

### Q: 是否可以同时使用多个 SDK 实例？
A: 可以，每个 Hook 实例都是独立的。但通常一个应用只需要一个 SDK 实例。

### Q: Hook 的性能如何？
A: Hook 使用了 React 的最佳实践，包括 `useCallback`、`useMemo` 等优化。轮询是可选的，不会影响不需要实时数据的组件。

### Q: 如何在 React Native 中使用？
A: 目前主要针对 Web 环境优化。React Native 支持可能需要额外的 polyfill 和配置。

---

**开始使用 React Hook 让 Passport 集成变得前所未有的简单！** 🚀 