You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
3.6 KiB
161 lines
3.6 KiB
/** |
|
* 用户状态管理 |
|
* 使用 Zustand + AsyncStorage 持久化 |
|
*/ |
|
|
|
import { create } from 'zustand'; |
|
import { useShallow } from 'zustand/react/shallow'; |
|
import AsyncStorage from '@react-native-async-storage/async-storage'; |
|
|
|
/** |
|
* 用户信息接口 |
|
*/ |
|
export interface User { |
|
id: string; |
|
username: string; |
|
email: string; |
|
avatar?: string; |
|
nickname?: string; |
|
phone?: string; |
|
createdAt?: string; |
|
} |
|
|
|
/** |
|
* 用户状态接口 |
|
*/ |
|
interface UserState { |
|
// 状态 |
|
user: User | null; |
|
isLoggedIn: boolean; |
|
token: string | null; |
|
|
|
// 操作 |
|
setUser: (user: User) => void; |
|
setToken: (token: string) => void; |
|
login: (user: User, token: string) => void; |
|
logout: () => void; |
|
updateUser: (updates: Partial<User>) => void; |
|
} |
|
|
|
/** |
|
* 用户状态 Store |
|
*/ |
|
export const useUserStore = create<UserState>()((set, get) => ({ |
|
// 初始状态 |
|
user: null, |
|
isLoggedIn: false, |
|
token: null, |
|
|
|
// 设置用户信息 |
|
setUser: (user) => { |
|
const newState = { user, isLoggedIn: true }; |
|
set(newState); |
|
// 手动持久化 |
|
AsyncStorage.setItem('user-storage', JSON.stringify(newState)); |
|
}, |
|
|
|
// 设置 token |
|
setToken: (token) => { |
|
set({ token }); |
|
// 手动持久化 - 延迟执行以确保状态已更新 |
|
setTimeout(() => { |
|
const state = get(); |
|
AsyncStorage.setItem('user-storage', JSON.stringify(state)); |
|
}, 0); |
|
}, |
|
|
|
// 登录 |
|
login: (user, token) => { |
|
const newState = { |
|
user, |
|
token, |
|
isLoggedIn: true, |
|
}; |
|
set(newState); |
|
|
|
// 同时保存 token 到 AsyncStorage(用于 API 请求) |
|
AsyncStorage.setItem('auth_token', token); |
|
// 手动持久化整个状态 |
|
AsyncStorage.setItem('user-storage', JSON.stringify(newState)); |
|
|
|
if (__DEV__) { |
|
console.log('✅ User logged in:', user.username); |
|
} |
|
}, |
|
|
|
// 登出 |
|
logout: () => { |
|
const newState = { |
|
user: null, |
|
token: null, |
|
isLoggedIn: false, |
|
}; |
|
set(newState); |
|
|
|
// 清除 AsyncStorage 中的 token |
|
AsyncStorage.removeItem('auth_token'); |
|
// 清除持久化状态 |
|
AsyncStorage.removeItem('user-storage'); |
|
|
|
if (__DEV__) { |
|
console.log('👋 User logged out'); |
|
} |
|
}, |
|
|
|
// 更新用户信息 |
|
updateUser: (updates) => { |
|
const currentUser = get().user; |
|
if (currentUser) { |
|
const newUser = { ...currentUser, ...updates }; |
|
set({ user: newUser }); |
|
// 手动持久化 |
|
AsyncStorage.setItem('user-storage', JSON.stringify({ ...get(), user: newUser })); |
|
|
|
if (__DEV__) { |
|
console.log('📝 User updated:', updates); |
|
} |
|
} |
|
}, |
|
})); |
|
|
|
// 从 AsyncStorage 恢复状态的函数 |
|
export const restoreUserState = async () => { |
|
try { |
|
const stored = await AsyncStorage.getItem('user-storage'); |
|
if (stored) { |
|
const state = JSON.parse(stored); |
|
useUserStore.setState(state); |
|
if (__DEV__) { |
|
console.log('✅ User state restored from storage'); |
|
} |
|
} |
|
} catch (error) { |
|
console.error('Failed to restore user state:', error); |
|
} |
|
}; |
|
|
|
/** |
|
* 选择器 Hooks(优化性能,避免不必要的重渲染) |
|
*/ |
|
|
|
// 获取用户信息 |
|
export const useUser = () => useUserStore((state) => state.user); |
|
|
|
// 获取登录状态 |
|
export const useIsLoggedIn = () => useUserStore((state) => state.isLoggedIn); |
|
|
|
// 获取 token |
|
export const useToken = () => useUserStore((state) => state.token); |
|
|
|
// 获取用户操作方法 |
|
// 使用 useShallow 避免每次渲染都返回新对象 |
|
export const useUserActions = () => |
|
useUserStore( |
|
useShallow((state) => ({ |
|
setUser: state.setUser, |
|
setToken: state.setToken, |
|
login: state.login, |
|
logout: state.logout, |
|
updateUser: state.updateUser, |
|
})) |
|
);
|
|
|