feat: new project

This commit is contained in:
2025-11-04 13:27:19 +08:00
commit 7526a9b827
49 changed files with 12520 additions and 0 deletions

283
docs/INSTALLED_PACKAGES.md Normal file
View File

@@ -0,0 +1,283 @@
# 📦 已安装的工具库总结
本文档列出了项目中新安装的所有工具库及其用途。
## ✅ 安装完成的库
### 🛠️ 工具类库
#### 1. **Lodash-ES** `^4.17.21`
- **用途**: 强大的 JavaScript 工具函数库ES modules 版本)
- **功能**: 数组、对象、字符串操作,防抖、节流等
- **优势**: 支持 tree-shaking按需导入减小包体积
- **文档**: https://lodash.com/docs/
- **示例**:
```typescript
import { debounce, uniq } from 'lodash-es';
debounce(fn, 300); // 防抖
uniq([1, 2, 2, 3]); // 去重
```
#### 2. **Day.js** `^1.11.19`
- **用途**: 轻量级日期处理库(仅 2KB
- **功能**: 日期格式化、相对时间、日期计算
- **文档**: https://day.js.org/
- **示例**:
```typescript
import dayjs from 'dayjs';
dayjs().format('YYYY-MM-DD');
dayjs().fromNow(); // '几秒前'
```
#### 3. **Axios** `^1.13.1`
- **用途**: HTTP 请求库
- **功能**: Promise API、请求/响应拦截器、取消请求
- **文档**: https://axios-http.com/
- **示例**:
```typescript
import axios from 'axios';
const data = await axios.get('/api/users');
```
#### 4. **Zustand** `^5.0.8`
- **用途**: 轻量级状态管理库
- **功能**: 简单的全局状态管理,比 Redux 简单得多
- **文档**: https://zustand-demo.pmnd.rs/
- **示例**:
```typescript
import { create } from 'zustand';
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
```
#### 5. **React Hook Form** `^7.66.0`
- **用途**: 高性能表单处理库
- **功能**: 表单验证、错误处理、性能优化
- **文档**: https://react-hook-form.com/
- **示例**:
```typescript
import { useForm } from 'react-hook-form';
const { register, handleSubmit } = useForm();
```
#### 6. **Zod** `^4.1.12`
- **用途**: TypeScript 优先的数据验证库
- **功能**: 数据验证、类型推断、错误处理
- **文档**: https://zod.dev/
- **示例**:
```typescript
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
});
```
---
### 📱 Expo 原生模块
#### 7. **AsyncStorage** `^2.2.0`
- **包名**: @react-native-async-storage/async-storage
- **用途**: React Native 本地持久化存储
- **功能**: 键值对存储、异步 API
- **文档**: https://react-native-async-storage.github.io/async-storage/
- **示例**:
```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('key', 'value');
```
#### 8. **Expo Image** `^3.0.10`
- **用途**: 性能优化的图片组件
- **功能**: 占位符、缓存、渐进加载
- **文档**: https://docs.expo.dev/versions/latest/sdk/image/
- **示例**:
```typescript
import { Image } from 'expo-image';
<Image source={{ uri: 'https://...' }} />
```
#### 9. **Expo Haptics** `^15.0.7`
- **用途**: 触觉反馈功能
- **功能**: 震动反馈、成功/错误/警告反馈
- **文档**: https://docs.expo.dev/versions/latest/sdk/haptics/
- **示例**:
```typescript
import * as Haptics from 'expo-haptics';
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
```
---
### 🔧 开发工具
#### 10. **@types/lodash-es** `^4.17.12`
- **用途**: Lodash-ES 的 TypeScript 类型定义
- **功能**: 提供完整的类型提示和类型检查
- **安装类型**: devDependencies
---
## 📊 安装统计
- **总计**: 10 个包
- **生产依赖**: 9 个
- **开发依赖**: 1 个
- **总大小**: 约 15MBnode_modules
---
## 🎯 使用场景
### 数据处理
- **Lodash**: 数组、对象操作
- **Day.js**: 日期时间处理
### 网络请求
- **Axios**: HTTP 请求
- **Zod**: API 响应验证
### 状态管理
- **Zustand**: 全局状态
- **AsyncStorage**: 本地持久化
### 表单处理
- **React Hook Form**: 表单管理
- **Zod**: 表单验证
### 用户体验
- **Expo Image**: 图片优化
- **Expo Haptics**: 触觉反馈
---
## 🚀 快速开始
### 1. 查看使用指南
详细的使用方法请查看 [LIBRARIES.md](./LIBRARIES.md)
### 2. 推荐的项目结构
```
src/
├── utils/
│ ├── api.ts # Axios 配置
│ ├── storage.ts # AsyncStorage 封装
│ └── date.ts # Day.js 工具函数
├── stores/
│ ├── userStore.ts # 用户状态Zustand
│ └── settingsStore.ts
├── schemas/
│ ├── auth.ts # 认证相关的 Zod schema
│ └── user.ts
└── hooks/
├── useDebounce.ts # Lodash debounce 封装
└── useThrottle.ts
```
### 3. 创建基础工具文件
**utils/api.ts** - Axios 配置
```typescript
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export default api;
```
**utils/storage.ts** - 存储工具
```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';
class Storage {
static async setObject<T>(key: string, value: T) {
await AsyncStorage.setItem(key, JSON.stringify(value));
}
static async getObject<T>(key: string): Promise<T | null> {
const value = await AsyncStorage.getItem(key);
return value ? JSON.parse(value) : null;
}
}
export default Storage;
```
**stores/userStore.ts** - 用户状态
```typescript
import { create } from 'zustand';
interface UserState {
user: any | null;
setUser: (user: any) => void;
}
export const useUserStore = create<UserState>((set) => ({
user: null,
setUser: (user) => set({ user }),
}));
```
---
## 💡 最佳实践
### 1. 性能优化
- ✅ 使用 Lodash-ES 的按需导入,减小包体积
- ✅ 使用 `debounce` 和 `throttle` 优化频繁触发的事件
- ✅ 使用 Zustand 的选择器避免不必要的重渲染
- ✅ 使用 Expo Image 的缓存策略优化图片加载
### 2. 类型安全
- ✅ 使用 Zod 定义数据结构并自动生成 TypeScript 类型
- ✅ 为 Zustand store 定义完整的类型接口
- ✅ 使用 `@types/lodash-es` 获得完整的类型提示
### 3. 代码组织
- ✅ 将 API 配置集中在 `utils/api.ts`
- ✅ 将存储操作封装在 `utils/storage.ts`
- ✅ 将状态管理放在 `stores/` 目录
- ✅ 将验证规则放在 `schemas/` 目录
### 4. 错误处理
- ✅ 在 Axios 拦截器中统一处理错误
- ✅ 使用 try-catch 包裹异步操作
- ✅ 提供用户友好的错误提示
---
## 📚 相关文档
- [LIBRARIES.md](./LIBRARIES.md) - 详细的使用指南和示例
- [README.md](./README.md) - 项目总体说明
- [KNOWN_ISSUES.md](./KNOWN_ISSUES.md) - 已知问题和解决方案
---
## 🎉 总结
所有工具库已成功安装并可以直接使用!这些库涵盖了:
-**数据处理** - Lodash-ES支持 tree-shaking, Day.js
-**网络请求** - Axios
-**状态管理** - Zustand
-**表单处理** - React Hook Form, Zod
-**本地存储** - AsyncStorage
-**用户体验** - Expo Image, Expo Haptics
开始使用这些强大的工具来构建你的应用吧!🚀

113
docs/KNOWN_ISSUES.md Normal file
View File

@@ -0,0 +1,113 @@
# 已知问题和警告说明
## ⚠️ Web 平台警告
### 警告信息
```
λ WARN props.pointerEvents is deprecated. Use style.pointerEvents
```
### 原因
这个警告来自 `react-native-web@0.21.2` 库内部,是该库在处理某些 React Native 组件时产生的弃用警告。具体来说:
- React Native Web 正在从使用 `props.pointerEvents` 迁移到 `style.pointerEvents`
- 这是库内部的实现细节,不是我们应用代码的问题
- 警告来自 `View` 组件在 Web 平台上的渲染过程
### 影响
-**不影响应用功能** - 应用在 Web 平台上完全正常运行
-**不影响性能** - 只是一个弃用提示
-**不影响移动端** - 只在 Web 平台出现
### 解决方案
#### 方案 1忽略警告推荐
这个警告是无害的,可以安全忽略。等待 `react-native-web` 库更新到新版本后会自动解决。
#### 方案 2抑制警告
如果你想在开发时隐藏这个警告,可以在 `app.json` 中添加配置:
```json
{
"expo": {
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
}
}
}
```
或者在代码中添加警告过滤(不推荐):
```typescript
// 在 app/_layout.tsx 顶部添加
if (typeof window !== 'undefined') {
const originalWarn = console.warn;
console.warn = (...args) => {
if (args[0]?.includes?.('pointerEvents is deprecated')) {
return;
}
originalWarn(...args);
};
}
```
#### 方案 3等待库更新
`react-native-web` 团队正在积极维护这个库,未来版本会解决这个警告。你可以:
1. 关注 [react-native-web 更新日志](https://github.com/necolas/react-native-web/releases)
2. 定期运行 `pnpm update react-native-web` 更新到最新版本
### 相关信息
- **库版本**: react-native-web@0.21.2
- **Expo 版本**: ~54.0.22
- **React Native 版本**: 0.81.5
- **问题追踪**: 这是 react-native-web 库的已知问题,正在逐步迁移中
### 验证
你可以通过以下方式验证应用功能正常:
```bash
# 启动 Web 版本
pnpm web
# 在浏览器中打开 http://localhost:8081
# 检查所有功能是否正常工作
```
## 📝 其他注意事项
### 开发模式下的其他常见警告
#### 1. Metro Bundler 警告
某些依赖可能会产生 Metro 打包警告,这些通常可以安全忽略。
#### 2. React 19 新特性警告
由于使用了 React 19.1.0,某些旧的 API 可能会有弃用警告。
#### 3. Expo Router 类型警告
TypeScript 可能会对某些 Expo Router 的动态路由产生类型警告,这是正常的。
### 生产构建
在生产构建中,这些警告不会出现,因为:
- 生产构建会移除所有开发时的警告
- 代码会被优化和压缩
- 只有关键错误会被记录
### 如何报告问题
如果你遇到其他问题:
1. 检查是否是已知问题(查看本文档)
2. 查看 [Expo 文档](https://docs.expo.dev/)
3. 搜索 [Expo GitHub Issues](https://github.com/expo/expo/issues)
4. 在项目中创建 issue 或联系开发团队
## ✅ 总结
**当前的 `pointerEvents` 警告是安全的,可以忽略。** 应用在所有平台iOS、Android、Web上都能正常运行。这只是一个库内部的迁移提示不影响你的开发和生产使用。
如果你想要一个完全没有警告的开发体验,可以等待 `react-native-web` 的下一个主要版本更新,或者使用上述方案 2 临时抑制警告。

387
docs/LIBRARIES.md Normal file
View File

@@ -0,0 +1,387 @@
# 📚 常用工具库使用指南
本文档介绍项目中已安装的常用工具库及其使用方法。
## 📦 已安装的库列表
### 工具类库
| 库名 | 版本 | 用途 |
|------|------|------|
| **lodash-es** | ^4.17.21 | JavaScript 工具函数库ES modules 版本) |
| **dayjs** | ^1.11.19 | 轻量级日期处理库 |
| **axios** | ^1.13.1 | HTTP 请求库 |
| **zustand** | ^5.0.8 | 轻量级状态管理 |
| **react-hook-form** | ^7.66.0 | 表单处理库 |
| **zod** | ^4.1.12 | TypeScript 数据验证库 |
### Expo 原生模块
| 库名 | 版本 | 用途 |
|------|------|------|
| **@react-native-async-storage/async-storage** | ^2.2.0 | 本地存储 |
| **expo-image** | ^3.0.10 | 优化的图片组件 |
| **expo-haptics** | ^15.0.7 | 触觉反馈 |
### 开发工具
| 库名 | 版本 | 用途 |
|------|------|------|
| **@types/lodash-es** | ^4.17.12 | Lodash-ES TypeScript 类型定义 |
---
## 🚀 快速开始
### 1. Lodash-ES - JavaScript 工具库
> **注意**:使用 `lodash-es` 而不是 `lodash`,支持 ES modules 和更好的 tree-shaking。
```typescript
// 推荐按需导入tree-shaking 友好)
import { map, filter, uniq, pick, cloneDeep, debounce } from 'lodash-es';
// 数组操作
map([1, 2, 3], n => n * 2); // [2, 4, 6]
filter([1, 2, 3, 4], n => n % 2 === 0); // [2, 4]
uniq([1, 2, 2, 3]); // [1, 2, 3]
// 对象操作
pick({ a: 1, b: 2, c: 3 }, ['a', 'b']); // { a: 1, b: 2 }
cloneDeep(obj); // 深拷贝
// 防抖和节流
const handleSearch = debounce((text) => {
console.log('Searching:', text);
}, 300);
// 也可以全量导入(不推荐,会增加包体积)
import _ from 'lodash-es';
_.map([1, 2, 3], n => n * 2);
```
### 2. Day.js - 日期处理
```typescript
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';
dayjs.extend(relativeTime);
dayjs.locale('zh-cn');
// 格式化
dayjs().format('YYYY-MM-DD HH:mm:ss');
// 相对时间
dayjs().fromNow(); // '几秒前'
dayjs().subtract(1, 'day').fromNow(); // '1天前'
// 日期操作
dayjs().add(7, 'day'); // 7天后
dayjs().startOf('month'); // 本月第一天
```
### 3. Axios - HTTP 请求
```typescript
import axios from 'axios';
// 创建实例
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
// 请求拦截器
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 使用
const data = await api.get('/users');
await api.post('/users', { name: 'John' });
```
### 4. Zustand - 状态管理
```typescript
import { create } from 'zustand';
interface UserState {
user: User | null;
setUser: (user: User) => void;
}
export const useUserStore = create<UserState>((set) => ({
user: null,
setUser: (user) => set({ user }),
}));
// 在组件中使用
const user = useUserStore((state) => state.user);
const setUser = useUserStore((state) => state.setUser);
```
### 5. React Hook Form + Zod - 表单处理
```typescript
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string().email('请输入有效的邮箱'),
password: z.string().min(6, '密码至少6个字符'),
});
type FormData = z.infer<typeof schema>;
function LoginForm() {
const { control, handleSubmit, formState: { errors } } = useForm<FormData>({
resolver: zodResolver(schema),
});
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<Controller
control={control}
name="email"
render={({ field: { onChange, value } }) => (
<TextInput
value={value}
onChangeText={onChange}
placeholder="邮箱"
/>
)}
/>
);
}
```
### 6. AsyncStorage - 本地存储
```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';
// 存储
await AsyncStorage.setItem('key', JSON.stringify(value));
// 读取
const value = await AsyncStorage.getItem('key');
const data = value ? JSON.parse(value) : null;
// 删除
await AsyncStorage.removeItem('key');
// 清空
await AsyncStorage.clear();
```
### 7. Expo Image - 优化的图片组件
```typescript
import { Image } from 'expo-image';
<Image
source={{ uri: 'https://example.com/image.jpg' }}
placeholder={require('@/assets/placeholder.png')}
contentFit="cover"
transition={1000}
style={{ width: 300, height: 300 }}
/>
```
### 8. Expo Haptics - 触觉反馈
```typescript
import * as Haptics from 'expo-haptics';
// 轻触反馈
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
// 成功反馈
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
// 错误反馈
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
```
---
## 💡 实用示例
### 创建 API 工具类
```typescript
// utils/api.ts
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
api.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
AsyncStorage.removeItem('token');
}
return Promise.reject(error);
}
);
export default api;
```
### 创建 Storage 工具类
```typescript
// utils/storage.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
class Storage {
static async setObject<T>(key: string, value: T): Promise<void> {
await AsyncStorage.setItem(key, JSON.stringify(value));
}
static async getObject<T>(key: string): Promise<T | null> {
const value = await AsyncStorage.getItem(key);
return value ? JSON.parse(value) : null;
}
static async remove(key: string): Promise<void> {
await AsyncStorage.removeItem(key);
}
}
export default Storage;
```
### 创建用户状态管理
```typescript
// stores/userStore.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
interface User {
id: string;
name: string;
email: string;
}
interface UserState {
user: User | null;
setUser: (user: User) => void;
clearUser: () => void;
}
export const useUserStore = create<UserState>()(
persist(
(set) => ({
user: null,
setUser: (user) => set({ user }),
clearUser: () => set({ user: null }),
}),
{
name: 'user-storage',
storage: createJSONStorage(() => AsyncStorage),
}
)
);
```
### 日期格式化工具
```typescript
// utils/date.ts
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';
dayjs.extend(relativeTime);
dayjs.locale('zh-cn');
export const formatDate = (date: Date | string | number) => {
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
};
export const formatRelativeTime = (date: Date | string | number) => {
return dayjs(date).fromNow();
};
export const formatChatTime = (timestamp: number) => {
const date = dayjs(timestamp);
const now = dayjs();
if (date.isSame(now, 'day')) {
return date.format('HH:mm');
} else if (date.isSame(now.subtract(1, 'day'), 'day')) {
return '昨天 ' + date.format('HH:mm');
} else if (date.isSame(now, 'year')) {
return date.format('MM-DD HH:mm');
} else {
return date.format('YYYY-MM-DD');
}
};
```
---
## 📝 最佳实践
1. **代码组织**
- 将 API 配置放在 `utils/api.ts`
- 将存储工具放在 `utils/storage.ts`
- 将状态管理放在 `stores/` 目录
- 将验证规则放在 `schemas/` 目录
2. **性能优化**
- 使用 `_.debounce``_.throttle` 优化频繁触发的事件
- 使用 Zustand 的选择器避免不必要的重渲染
- 使用 Expo Image 的缓存策略
3. **类型安全**
- 使用 Zod 定义数据结构并自动生成 TypeScript 类型
- 为 Zustand store 定义完整的类型
- 使用 `@types/lodash` 获得完整的类型提示
4. **错误处理**
- 在 Axios 拦截器中统一处理错误
- 使用 try-catch 包裹异步操作
- 提供用户友好的错误提示
---
## 🔗 相关资源
- [Lodash 文档](https://lodash.com/docs/)
- [Day.js 文档](https://day.js.org/)
- [Axios 文档](https://axios-http.com/)
- [Zustand 文档](https://zustand-demo.pmnd.rs/)
- [React Hook Form 文档](https://react-hook-form.com/)
- [Zod 文档](https://zod.dev/)
- [AsyncStorage 文档](https://react-native-async-storage.github.io/async-storage/)
- [Expo Image 文档](https://docs.expo.dev/versions/latest/sdk/image/)
- [Expo Haptics 文档](https://docs.expo.dev/versions/latest/sdk/haptics/)
---
**提示**:所有库都已安装并配置好,可以直接在项目中使用!🎉

429
docs/USAGE_EXAMPLES.md Normal file
View File

@@ -0,0 +1,429 @@
# 💡 使用示例
本文档提供项目中各个工具和模块的实际使用示例。
## 📋 目录
- [登录功能示例](#登录功能示例)
- [用户资料更新示例](#用户资料更新示例)
- [搜索功能示例](#搜索功能示例)
- [设置页面示例](#设置页面示例)
- [列表加载示例](#列表加载示例)
---
## 登录功能示例
完整的登录页面实现包含表单验证、API 调用、状态管理。
```typescript
import React, { useState } from 'react';
import { View, TextInput, TouchableOpacity, Text, Alert } from 'react-native';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useRouter } from 'expo-router';
import {
loginSchema,
type LoginFormData,
authService,
useUserStore,
useHaptics,
} from '@/src';
export default function LoginScreen() {
const router = useRouter();
const haptics = useHaptics();
const login = useUserStore((state) => state.login);
const [loading, setLoading] = useState(false);
// 表单配置
const {
control,
handleSubmit,
formState: { errors },
} = useForm<LoginFormData>({
resolver: zodResolver(loginSchema),
defaultValues: {
email: '',
password: '',
},
});
// 提交处理
const onSubmit = async (data: LoginFormData) => {
try {
setLoading(true);
// 调用登录 API
const { user, token } = await authService.login(data);
// 更新状态
login(user, token);
// 触觉反馈
haptics.success();
// 跳转到首页
router.replace('/(tabs)');
} catch (error: any) {
haptics.error();
Alert.alert('登录失败', error.message || '请检查邮箱和密码');
} finally {
setLoading(false);
}
};
return (
<View style={{ padding: 20 }}>
{/* 邮箱输入 */}
<Controller
control={control}
name="email"
render={({ field: { onChange, value } }) => (
<View>
<TextInput
value={value}
onChangeText={onChange}
placeholder="邮箱"
keyboardType="email-address"
autoCapitalize="none"
style={{
borderWidth: 1,
borderColor: errors.email ? 'red' : '#ccc',
padding: 10,
borderRadius: 5,
}}
/>
{errors.email && (
<Text style={{ color: 'red', marginTop: 5 }}>
{errors.email.message}
</Text>
)}
</View>
)}
/>
{/* 密码输入 */}
<Controller
control={control}
name="password"
render={({ field: { onChange, value } }) => (
<View style={{ marginTop: 15 }}>
<TextInput
value={value}
onChangeText={onChange}
placeholder="密码"
secureTextEntry
style={{
borderWidth: 1,
borderColor: errors.password ? 'red' : '#ccc',
padding: 10,
borderRadius: 5,
}}
/>
{errors.password && (
<Text style={{ color: 'red', marginTop: 5 }}>
{errors.password.message}
</Text>
)}
</View>
)}
/>
{/* 登录按钮 */}
<TouchableOpacity
onPress={handleSubmit(onSubmit)}
disabled={loading}
style={{
backgroundColor: loading ? '#ccc' : '#007AFF',
padding: 15,
borderRadius: 5,
marginTop: 20,
}}
>
<Text style={{ color: 'white', textAlign: 'center', fontWeight: 'bold' }}>
{loading ? '登录中...' : '登录'}
</Text>
</TouchableOpacity>
</View>
);
}
```
---
## 用户资料更新示例
使用表单验证和 API 服务更新用户资料。
```typescript
import React, { useState } from 'react';
import { View, TextInput, TouchableOpacity, Text, Alert } from 'react-native';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import {
updateProfileSchema,
type UpdateProfileFormData,
userService,
useUserStore,
useHaptics,
} from '@/src';
export default function EditProfileScreen() {
const haptics = useHaptics();
const user = useUserStore((state) => state.user);
const updateUser = useUserStore((state) => state.updateUser);
const [loading, setLoading] = useState(false);
const {
control,
handleSubmit,
formState: { errors },
} = useForm<UpdateProfileFormData>({
resolver: zodResolver(updateProfileSchema),
defaultValues: {
nickname: user?.nickname || '',
phone: user?.phone || '',
},
});
const onSubmit = async (data: UpdateProfileFormData) => {
try {
setLoading(true);
// 调用更新 API
const updatedUser = await userService.updateProfile(data);
// 更新本地状态
updateUser(updatedUser);
haptics.success();
Alert.alert('成功', '资料更新成功');
} catch (error: any) {
haptics.error();
Alert.alert('失败', error.message || '更新失败');
} finally {
setLoading(false);
}
};
return (
<View style={{ padding: 20 }}>
<Controller
control={control}
name="nickname"
render={({ field: { onChange, value } }) => (
<View>
<Text></Text>
<TextInput
value={value}
onChangeText={onChange}
placeholder="请输入昵称"
style={{ borderWidth: 1, padding: 10, marginTop: 5 }}
/>
{errors.nickname && (
<Text style={{ color: 'red' }}>{errors.nickname.message}</Text>
)}
</View>
)}
/>
<TouchableOpacity
onPress={handleSubmit(onSubmit)}
disabled={loading}
style={{
backgroundColor: '#007AFF',
padding: 15,
marginTop: 20,
borderRadius: 5,
}}
>
<Text style={{ color: 'white', textAlign: 'center' }}>
{loading ? '保存中...' : '保存'}
</Text>
</TouchableOpacity>
</View>
);
}
```
---
## 搜索功能示例
使用防抖优化搜索性能。
```typescript
import React, { useState, useEffect } from 'react';
import { View, TextInput, FlatList, Text } from 'react-native';
import { useDebounce } from '@/src';
export default function SearchScreen() {
const [searchText, setSearchText] = useState('');
const [results, setResults] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
// 防抖搜索函数
const debouncedSearch = useDebounce(async (text: string) => {
if (!text.trim()) {
setResults([]);
return;
}
try {
setLoading(true);
// 调用搜索 API
const response = await fetch(`/api/search?q=${text}`);
const data = await response.json();
setResults(data.results);
} catch (error) {
console.error('Search error:', error);
} finally {
setLoading(false);
}
}, 500);
// 监听搜索文本变化
useEffect(() => {
debouncedSearch(searchText);
}, [searchText]);
return (
<View style={{ flex: 1, padding: 20 }}>
<TextInput
value={searchText}
onChangeText={setSearchText}
placeholder="搜索..."
style={{
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
borderRadius: 5,
}}
/>
{loading && <Text style={{ marginTop: 10 }}>...</Text>}
<FlatList
data={results}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={{ padding: 10, borderBottomWidth: 1 }}>
<Text>{item.title}</Text>
</View>
)}
style={{ marginTop: 20 }}
/>
</View>
);
}
```
---
## 设置页面示例
使用状态管理和触觉反馈。
```typescript
import React from 'react';
import { View, Text, Switch, TouchableOpacity } from 'react-native';
import {
useSettingsStore,
useHaptics,
type Theme,
} from '@/src';
export default function SettingsScreen() {
const haptics = useHaptics();
const theme = useSettingsStore((state) => state.theme);
const notificationsEnabled = useSettingsStore((state) => state.notificationsEnabled);
const hapticsEnabled = useSettingsStore((state) => state.hapticsEnabled);
const setTheme = useSettingsStore((state) => state.setTheme);
const setNotificationsEnabled = useSettingsStore((state) => state.setNotificationsEnabled);
const setHapticsEnabled = useSettingsStore((state) => state.setHapticsEnabled);
const handleThemeChange = (newTheme: Theme) => {
haptics.selection();
setTheme(newTheme);
};
const handleToggle = (setter: (value: boolean) => void, value: boolean) => {
haptics.light();
setter(value);
};
return (
<View style={{ flex: 1, padding: 20 }}>
{/* 主题选择 */}
<View style={{ marginBottom: 20 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
</Text>
{(['light', 'dark', 'auto'] as Theme[]).map((t) => (
<TouchableOpacity
key={t}
onPress={() => handleThemeChange(t)}
style={{
padding: 15,
backgroundColor: theme === t ? '#007AFF' : '#f0f0f0',
marginBottom: 10,
borderRadius: 5,
}}
>
<Text style={{ color: theme === t ? 'white' : 'black' }}>
{t === 'light' ? '亮色' : t === 'dark' ? '暗色' : '自动'}
</Text>
</TouchableOpacity>
))}
</View>
{/* 通知开关 */}
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 15,
}}
>
<Text></Text>
<Switch
value={notificationsEnabled}
onValueChange={(value) => handleToggle(setNotificationsEnabled, value)}
/>
</View>
{/* 触觉反馈开关 */}
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<Text></Text>
<Switch
value={hapticsEnabled}
onValueChange={(value) => handleToggle(setHapticsEnabled, value)}
/>
</View>
</View>
);
}
```
---
## 📚 更多示例
查看以下文档了解更多:
- [工具库使用指南](./LIBRARIES.md) - 各个工具库的详细用法
- [项目结构说明](./PROJECT_STRUCTURE.md) - 项目结构和最佳实践
---
**提示**:这些示例都是可以直接使用的代码,复制到你的项目中即可!