Files
flyer-crawler.projectium.com/src/providers/UserDataProvider.tsx
Torben Sorensen 38eb810e7a
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 11m55s
logging the frontend loop
2025-12-30 23:28:38 -08:00

75 lines
2.7 KiB
TypeScript

// src/providers/UserDataProvider.tsx
import { logger } from '../services/logger.client';
import React, { useState, useEffect, useMemo, ReactNode, useCallback } from 'react';
import { UserDataContext } from '../contexts/UserDataContext';
import type { MasterGroceryItem, ShoppingList } from '../types';
import * as apiClient from '../services/apiClient';
import { useApiOnMount } from '../hooks/useApiOnMount';
import { useAuth } from '../hooks/useAuth';
export const UserDataProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { userProfile } = useAuth();
// Wrap the API calls in useCallback to prevent unnecessary re-renders.
const fetchWatchedItemsFn = useCallback(
() => apiClient.fetchWatchedItems(),
[],
);
const fetchShoppingListsFn = useCallback(() => apiClient.fetchShoppingLists(), []);
const {
data: watchedItemsData,
loading: isLoadingWatched,
error: watchedItemsError,
} = useApiOnMount<MasterGroceryItem[], []>(fetchWatchedItemsFn, [userProfile], {
enabled: !!userProfile,
});
const {
data: shoppingListsData,
loading: isLoadingShoppingLists,
error: shoppingListsError,
} = useApiOnMount<ShoppingList[], []>(fetchShoppingListsFn, [userProfile], {
enabled: !!userProfile,
});
const [watchedItems, setWatchedItems] = useState<MasterGroceryItem[]>([]);
const [shoppingLists, setShoppingLists] = useState<ShoppingList[]>([]);
// This effect synchronizes the local state (watchedItems, shoppingLists) with the
// data fetched by the useApiOnMount hooks. It also handles cleanup on user logout.
useEffect(() => {
// When the user logs out (user becomes null), immediately clear all user-specific data.
// This also serves to clear out old data when a new user logs in, before their new data arrives.
if (!userProfile) {
setWatchedItems([]);
setShoppingLists([]);
return;
}
// Once data for the new user is fetched, update the state.
if (watchedItemsData) setWatchedItems(watchedItemsData);
if (shoppingListsData) setShoppingLists(shoppingListsData);
}, [userProfile, watchedItemsData, shoppingListsData]);
const value = useMemo(
() => ({
watchedItems,
shoppingLists,
setWatchedItems,
setShoppingLists,
isLoading: !!userProfile && (isLoadingWatched || isLoadingShoppingLists),
error: watchedItemsError?.message || shoppingListsError?.message || null,
}),
[
watchedItems,
shoppingLists,
userProfile,
isLoadingWatched,
isLoadingShoppingLists,
watchedItemsError,
shoppingListsError,
],
);
return <UserDataContext.Provider value={value}>{children}</UserDataContext.Provider>;
};