All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 11m55s
75 lines
2.7 KiB
TypeScript
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>;
|
|
};
|