Automatically migrate old localStorage format where user object has userId field to new format with id field. This prevents users from needing to re-login after the backend API response changed from userId to id. Changes: - Added migrate function to Zustand persist config to handle userId → id migration - Added post-hydration safety check in onRehydrateStorage callback - Added detailed console.log for debugging migration process Fixes: User data mismatch after API response format change 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { create } from 'zustand';
|
|
import { persist } from 'zustand/middleware';
|
|
import { User } from '@/types/user';
|
|
|
|
interface AuthState {
|
|
user: User | null;
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
isHydrated: boolean;
|
|
|
|
setUser: (user: User) => void;
|
|
clearUser: () => void;
|
|
setLoading: (loading: boolean) => void;
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
persist(
|
|
(set) => ({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
isLoading: true,
|
|
isHydrated: false,
|
|
|
|
setUser: (user) =>
|
|
set({ user, isAuthenticated: true, isLoading: false }),
|
|
clearUser: () =>
|
|
set({ user: null, isAuthenticated: false, isLoading: false }),
|
|
setLoading: (loading) => set({ isLoading: loading }),
|
|
}),
|
|
{
|
|
name: 'colaflow-auth',
|
|
partialize: (state) => ({
|
|
user: state.user,
|
|
isAuthenticated: state.isAuthenticated,
|
|
}),
|
|
// 数据迁移函数:将旧格式的 userId 转换为新格式的 id
|
|
migrate: (persistedState: any, version: number) => {
|
|
console.log('[AuthStore] Migrating persisted state', { version, persistedState });
|
|
|
|
// 如果存在旧的 userId 字段,迁移到 id
|
|
if (persistedState?.user?.userId && !persistedState?.user?.id) {
|
|
console.log('[AuthStore] Migrating userId to id');
|
|
persistedState.user.id = persistedState.user.userId;
|
|
delete persistedState.user.userId;
|
|
}
|
|
|
|
return persistedState;
|
|
},
|
|
onRehydrateStorage: () => (state) => {
|
|
console.log('[AuthStore] Hydration started');
|
|
if (state) {
|
|
// 额外的安全检查:确保 user 对象有 id 字段
|
|
if (state.user && (state.user as any).userId && !state.user.id) {
|
|
console.log('[AuthStore] Post-hydration migration: userId -> id');
|
|
state.user.id = (state.user as any).userId;
|
|
delete (state.user as any).userId;
|
|
}
|
|
|
|
state.isHydrated = true;
|
|
console.log('[AuthStore] Hydration completed', {
|
|
userId: state.user?.id,
|
|
isAuthenticated: state.isAuthenticated
|
|
});
|
|
}
|
|
},
|
|
}
|
|
)
|
|
);
|