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

89 lines
2.8 KiB
TypeScript
Raw Normal View History

import { useCallback, useEffect, useRef } from 'react';
import { usePostManagerStore } from './postStore';
import { postManager } from './PostManager';
import type { Post } from '../../types';
import { POST_LIST_PAGE_SIZE } from '../postListSources';
import type { PostListTab } from '../postListSources';
export interface UsePostListResult {
posts: Post[];
isLoading: boolean;
refresh: () => Promise<void>;
}
export function usePostList(
type: PostListTab = 'hot',
page = 1,
pageSize = POST_LIST_PAGE_SIZE
): UsePostListResult {
const posts = usePostManagerStore(state => {
const key = `list:${type}:${page}:${pageSize}`;
return state.listsMap.get(key)?.data ?? [];
});
const isLoading = usePostManagerStore(state => {
const key = `list:${type}:${page}:${pageSize}`;
return state.loadingListKeys.has(key);
});
const lastFetchedRef = useRef<string | null>(null);
useEffect(() => {
const key = `${type}:${page}:${pageSize}`;
if (lastFetchedRef.current !== key) {
lastFetchedRef.current = key;
usePostManagerStore.getState().setLoadingList(type, page, pageSize, true);
postManager.getPosts(type, page, pageSize).finally(() => {
usePostManagerStore.getState().setLoadingList(type, page, pageSize, false);
});
}
}, [type, page, pageSize]);
const refresh = useCallback(async () => {
usePostManagerStore.getState().setLoadingList(type, page, pageSize, true);
try {
await postManager.getPosts(type, page, pageSize, true);
} finally {
usePostManagerStore.getState().setLoadingList(type, page, pageSize, false);
}
}, [type, page, pageSize]);
return { posts, isLoading, refresh };
}
export interface UsePostDetailResult {
post: Post | null;
isLoading: boolean;
refresh: () => Promise<Post | null>;
}
export function usePostDetail(postId: string | undefined | null): UsePostDetailResult {
const post = usePostManagerStore(state =>
postId ? (state.detailsMap.get(postId)?.data ?? null) : null
);
const isLoading = usePostManagerStore(state =>
postId ? state.loadingDetailIds.has(postId) : false
);
const lastFetchedRef = useRef<string | null>(null);
useEffect(() => {
if (!postId) return;
if (lastFetchedRef.current !== postId) {
lastFetchedRef.current = postId;
usePostManagerStore.getState().setLoadingDetail(postId, true);
postManager.getPostDetail(postId).finally(() => {
usePostManagerStore.getState().setLoadingDetail(postId, false);
});
}
}, [postId]);
const refresh = useCallback(async () => {
if (!postId) return null;
usePostManagerStore.getState().setLoadingDetail(postId, true);
try {
return await postManager.getPostDetail(postId, true);
} finally {
usePostManagerStore.getState().setLoadingDetail(postId, false);
}
}, [postId]);
return { post, isLoading, refresh };
}