aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/src/components/FeedSidebar.tsx
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-14 12:17:23 +0900
committernsfisis <nsfisis@gmail.com>2026-02-14 12:17:23 +0900
commitfffd36268a216044523c3f5227c3d375608c36dc (patch)
treeb289735cb9d478af763775af9b15214b9595e747 /frontend/src/components/FeedSidebar.tsx
parent2889b562e64993482bd13fd806af8ed0865bab8b (diff)
downloadfeedaka-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/components/FeedSidebar.tsx')
-rw-r--r--frontend/src/components/FeedSidebar.tsx26
1 files changed, 3 insertions, 23 deletions
diff --git a/frontend/src/components/FeedSidebar.tsx b/frontend/src/components/FeedSidebar.tsx
index 4f50566..6c385c5 100644
--- a/frontend/src/components/FeedSidebar.tsx
+++ b/frontend/src/components/FeedSidebar.tsx
@@ -1,9 +1,6 @@
-import { useCallback, useEffect, useState } from "react";
+import { useAtomValue } from "jotai";
import { useLocation, useSearch } from "wouter";
-import type { components } from "../api/generated";
-import { api } from "../services/api-client";
-
-type Feed = components["schemas"]["Feed"];
+import { feedsAtom } from "../atoms";
interface Props {
basePath: string;
@@ -15,21 +12,7 @@ export function FeedSidebar({ basePath }: Props) {
const params = new URLSearchParams(search);
const selectedFeedId = params.get("feed");
- const [feeds, setFeeds] = useState<Feed[]>([]);
- const [fetching, setFetching] = useState(true);
-
- const fetchFeeds = useCallback(async () => {
- setFetching(true);
- const { data } = await api.GET("/api/feeds");
- if (data) {
- setFeeds(data);
- }
- setFetching(false);
- }, []);
-
- useEffect(() => {
- fetchFeeds();
- }, [fetchFeeds]);
+ const { data: feeds } = useAtomValue(feedsAtom);
const handleSelect = (feedId: string | null) => {
if (feedId) {
@@ -58,9 +41,6 @@ export function FeedSidebar({ basePath }: Props) {
All feeds
</button>
</li>
- {fetching && (
- <li className="px-3 py-1.5 text-xs text-stone-400">Loading...</li>
- )}
{feeds.map((feed) => (
<li key={feed.id}>
<button