Files
frontend/src/stores/user/hooks.ts

137 lines
4.0 KiB
TypeScript
Raw Normal View History

/**
* React Hooks
*/
import { useCallback, useEffect, useState } from 'react';
import { useUserManagerStore } from './userStore';
import { userManager } from './UserManager';
import type { UserDTO } from '../../types/dto';
// ==================== useCurrentUser ====================
export interface UseCurrentUserResult {
user: UserDTO | null;
isLoading: boolean;
refresh: () => Promise<UserDTO | null>;
}
/**
* hook
*
*/
export function useCurrentUser(): UseCurrentUserResult {
const user = useUserManagerStore(state => state.currentUser);
const isLoading = useUserManagerStore(state => state.isLoadingCurrentUser);
const [hasFetched, setHasFetched] = useState(false);
useEffect(() => {
if (!hasFetched) {
setHasFetched(true);
useUserManagerStore.getState().setLoadingCurrentUser(true);
userManager.getCurrentUser().finally(() => {
useUserManagerStore.getState().setLoadingCurrentUser(false);
});
}
}, [hasFetched]);
const refresh = useCallback(async () => {
useUserManagerStore.getState().setLoadingCurrentUser(true);
try {
return await userManager.getCurrentUser(true);
} finally {
useUserManagerStore.getState().setLoadingCurrentUser(false);
}
}, []);
return { user, isLoading, refresh };
}
// ==================== useUser ====================
export interface UseUserResult {
user: UserDTO | null;
isLoading: boolean;
refresh: () => Promise<UserDTO | null>;
}
/**
* ID hook
*
*/
export function useUser(userId: string | undefined | null): UseUserResult {
const user = useUserManagerStore(state =>
userId ? (state.usersMap.get(userId)?.data ?? null) : null
);
const isLoading = useUserManagerStore(state =>
userId ? state.loadingUserIds.has(userId) : false
);
const [hasFetched, setHasFetched] = useState(false);
useEffect(() => {
if (!userId) return;
if (!hasFetched) {
setHasFetched(true);
useUserManagerStore.getState().setLoadingUser(userId, true);
userManager.getUserById(userId).finally(() => {
useUserManagerStore.getState().setLoadingUser(userId, false);
});
}
}, [userId, hasFetched]);
const refresh = useCallback(async () => {
if (!userId) return null;
useUserManagerStore.getState().setLoadingUser(userId, true);
try {
return await userManager.getUserById(userId, true);
} finally {
useUserManagerStore.getState().setLoadingUser(userId, false);
}
}, [userId]);
return { user, isLoading, refresh };
}
// ==================== useUsers ====================
export interface UseUsersResult {
getUser: (id: string) => UserDTO | null;
refreshUser: (id: string) => Promise<UserDTO | null>;
}
/**
* <EFBFBD><EFBFBD>?hook
*
*/
export function useUsers(userIds: string[]): UseUsersResult {
const usersMap = useUserManagerStore(state => state.usersMap);
const loadingUserIds = useUserManagerStore(state => state.loadingUserIds);
const [fetchedIds, setFetchedIds] = useState<Set<string>>(new Set());
useEffect(() => {
userIds.forEach(id => {
if (!fetchedIds.has(id) && !loadingUserIds.has(id)) {
setFetchedIds(prev => new Set(prev).add(id));
useUserManagerStore.getState().setLoadingUser(id, true);
userManager.getUserById(id).finally(() => {
useUserManagerStore.getState().setLoadingUser(id, false);
});
}
});
}, [userIds, fetchedIds, loadingUserIds]);
const getUser = useCallback((id: string) => {
return usersMap.get(id)?.data ?? null;
}, [usersMap]);
const refreshUser = useCallback(async (id: string) => {
useUserManagerStore.getState().setLoadingUser(id, true);
try {
return await userManager.getUserById(id, true);
} finally {
useUserManagerStore.getState().setLoadingUser(id, false);
}
}, []);
return { getUser, refreshUser };
}