/** * 帖子相关 React Hooks */ import { useCallback, useEffect, useState } 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'; // ==================== usePostList ==================== export interface UsePostListResult { posts: Post[]; isLoading: boolean; refresh: () => Promise; } /** * 获取帖子列表 hook */ 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 [hasFetched, setHasFetched] = useState(false); useEffect(() => { if (!hasFetched) { setHasFetched(true); usePostManagerStore.getState().setLoadingList(type, page, pageSize, true); postManager.getPosts(type, page, pageSize).finally(() => { usePostManagerStore.getState().setLoadingList(type, page, pageSize, false); }); } }, [type, page, pageSize, hasFetched]); 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 }; } // ==================== usePostDetail ==================== export interface UsePostDetailResult { post: Post | null; isLoading: boolean; refresh: () => Promise; } /** * 获取帖子详情 hook */ 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 [hasFetched, setHasFetched] = useState(false); useEffect(() => { if (!postId) return; if (!hasFetched) { setHasFetched(true); usePostManagerStore.getState().setLoadingDetail(postId, true); postManager.getPostDetail(postId).finally(() => { usePostManagerStore.getState().setLoadingDetail(postId, false); }); } }, [postId, hasFetched]); 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 }; }