aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/src/contexts
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/contexts
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/contexts')
-rw-r--r--frontend/src/contexts/AuthContext.tsx74
1 files changed, 0 insertions, 74 deletions
diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx
index 9b157cb..e69de29 100644
--- a/frontend/src/contexts/AuthContext.tsx
+++ b/frontend/src/contexts/AuthContext.tsx
@@ -1,74 +0,0 @@
-import {
- createContext,
- type ReactNode,
- useCallback,
- useContext,
- useEffect,
- useState,
-} from "react";
-import { api } from "../services/api-client";
-
-type LoginResult = { success: true } | { success: false; error: string };
-
-interface AuthContextType {
- isLoggedIn: boolean;
- isLoading: boolean;
- login: (username: string, password: string) => Promise<LoginResult>;
- logout: () => Promise<void>;
-}
-
-const AuthContext = createContext<AuthContextType | undefined>(undefined);
-
-export function AuthProvider({ children }: { children: ReactNode }) {
- const [isLoggedIn, setIsLoggedIn] = useState(false);
- const [isLoading, setIsLoading] = useState(true);
-
- const checkAuth = useCallback(async () => {
- const { data } = await api.GET("/api/auth/me");
- setIsLoggedIn(!!data);
- setIsLoading(false);
- }, []);
-
- useEffect(() => {
- checkAuth();
- }, [checkAuth]);
-
- const login = async (
- username: string,
- password: string,
- ): Promise<LoginResult> => {
- const { data, error } = await api.POST("/api/auth/login", {
- body: { username, password },
- });
-
- if (error) {
- return { success: false, error: error.message };
- }
-
- if (data?.user) {
- setIsLoggedIn(true);
- return { success: true };
- }
-
- return { success: false, error: "Invalid username or password" };
- };
-
- const logout = async () => {
- await api.POST("/api/auth/logout");
- setIsLoggedIn(false);
- };
-
- return (
- <AuthContext.Provider value={{ isLoggedIn, isLoading, login, logout }}>
- {children}
- </AuthContext.Provider>
- );
-}
-
-export function useAuth() {
- const context = useContext(AuthContext);
- if (context === undefined) {
- throw new Error("useAuth must be used within an AuthProvider");
- }
- return context;
-}