diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-02-14 12:17:23 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-02-14 12:17:23 +0900 |
| commit | fffd36268a216044523c3f5227c3d375608c36dc (patch) | |
| tree | b289735cb9d478af763775af9b15214b9595e747 /frontend/src/hooks | |
| parent | 2889b562e64993482bd13fd806af8ed0865bab8b (diff) | |
| download | feedaka-fffd36268a216044523c3f5227c3d375608c36dc.tar.gz feedaka-fffd36268a216044523c3f5227c3d375608c36dc.tar.zst feedaka-fffd36268a216044523c3f5227c3d375608c36dc.zip | |
refactor(frontend): migrate state management to jotai and jotai-tanstack-query
Replace React Context + manual useEffect data fetching with jotai atoms
for state management and jotai-tanstack-query for server state caching.
- Add jotai, jotai-tanstack-query, @tanstack/query-core dependencies
- Create atoms for auth (primitive + action), feeds (suspense query),
and articles (infinite query with cursor-based pagination)
- Wire up Provider, HydrateQueryClient, and StoreInitializer in main.tsx
- Migrate all components from useAuth() context to jotai atoms
- Replace manual fetch logic in FeedSidebar/FeedList with feedsAtom
- Replace usePaginatedArticles hook with articlesInfiniteAtom
- Add queryClient.invalidateQueries() after mutations for automatic
cache refresh
- Add ErrorBoundary and LoadingSpinner components for Suspense support
- Remove callback prop chains (onFeedAdded, onFeedChanged, etc.)
in favor of query invalidation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'frontend/src/hooks')
| -rw-r--r-- | frontend/src/hooks/usePaginatedArticles.ts | 80 |
1 files changed, 0 insertions, 80 deletions
diff --git a/frontend/src/hooks/usePaginatedArticles.ts b/frontend/src/hooks/usePaginatedArticles.ts index 5ddf888..e69de29 100644 --- a/frontend/src/hooks/usePaginatedArticles.ts +++ b/frontend/src/hooks/usePaginatedArticles.ts @@ -1,80 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import type { components } from "../api/generated"; -import { api } from "../services/api-client"; - -export type ArticleType = components["schemas"]["Article"]; - -interface UsePaginatedArticlesOptions { - isReadView: boolean; - feedId: string | null; -} - -interface UsePaginatedArticlesResult { - articles: ArticleType[]; - hasNextPage: boolean; - loading: boolean; - loadingMore: boolean; - loadMore: () => void; - error: Error | null; -} - -export function usePaginatedArticles({ - isReadView, - feedId, -}: UsePaginatedArticlesOptions): UsePaginatedArticlesResult { - const [articles, setArticles] = useState<ArticleType[]>([]); - const [hasNextPage, setHasNextPage] = useState(false); - const [endCursor, setEndCursor] = useState<string | null>(null); - const [loading, setLoading] = useState(true); - const [loadingMore, setLoadingMore] = useState(false); - const [error, setError] = useState<Error | null>(null); - - const fetchArticles = useCallback( - async (after: string | null, append: boolean) => { - const query: { feedId?: string; after?: string } = {}; - if (feedId) query.feedId = feedId; - if (after) query.after = after; - - const endpoint = isReadView - ? "/api/articles/read" - : "/api/articles/unread"; - - const { data } = await api.GET(endpoint, { - params: { query }, - }); - - if (!data) { - setError(new Error("Failed to fetch articles")); - return; - } - - if (data) { - setArticles((prev) => - append ? [...prev, ...data.articles] : data.articles, - ); - setHasNextPage(data.pageInfo.hasNextPage); - setEndCursor(data.pageInfo.endCursor ?? null); - setError(null); - } - }, - [isReadView, feedId], - ); - - // Reset and fetch on feedId or view change - useEffect(() => { - setArticles([]); - setEndCursor(null); - setHasNextPage(false); - setLoading(true); - setError(null); - fetchArticles(null, false).finally(() => setLoading(false)); - }, [fetchArticles]); - - const loadMore = useCallback(() => { - if (!hasNextPage || loadingMore) return; - setLoadingMore(true); - fetchArticles(endCursor, true).finally(() => setLoadingMore(false)); - }, [fetchArticles, endCursor, hasNextPage, loadingMore]); - - return { articles, hasNextPage, loading, loadingMore, loadMore, error }; -} |
