From 0ef5b43db4e3894844c41382bb3b7674e4a8882a Mon Sep 17 00:00:00 2001 From: Bentroen <29354120+Bentroen@users.noreply.github.com> Date: Mon, 27 Apr 2026 10:23:11 -0300 Subject: [PATCH] fix recent songs stuck in loading state after filtering by category Removes re-fetching on `useState` and calls it explicitly when loading a new page or changing the category. Fixes #87 --- .../browse/components/HomePageComponent.tsx | 2 - .../client/context/RecentSongs.context.tsx | 130 ++++++++---------- 2 files changed, 60 insertions(+), 72 deletions(-) diff --git a/apps/frontend/src/modules/browse/components/HomePageComponent.tsx b/apps/frontend/src/modules/browse/components/HomePageComponent.tsx index 50996e86..5abfb33e 100644 --- a/apps/frontend/src/modules/browse/components/HomePageComponent.tsx +++ b/apps/frontend/src/modules/browse/components/HomePageComponent.tsx @@ -21,7 +21,6 @@ import { CategoryButtonGroup } from './client/CategoryButton'; import { useFeaturedSongsProvider } from './client/context/FeaturedSongs.context'; import { useRecentSongsProvider, - useRecentSongsPageLoader, useRecentSongsCategoriesLoader, } from './client/context/RecentSongs.context'; import LoadMoreButton from './client/LoadMoreButton'; @@ -31,7 +30,6 @@ import SongCardGroup from './SongCardGroup'; export const HomePageComponent = () => { // Initialize sync hooks for proper effect handling - useRecentSongsPageLoader(); useRecentSongsCategoriesLoader(); const { featuredSongsPage, timespan } = useFeaturedSongsProvider(); diff --git a/apps/frontend/src/modules/browse/components/client/context/RecentSongs.context.tsx b/apps/frontend/src/modules/browse/components/client/context/RecentSongs.context.tsx index 60a10135..84fd2547 100644 --- a/apps/frontend/src/modules/browse/components/client/context/RecentSongs.context.tsx +++ b/apps/frontend/src/modules/browse/components/client/context/RecentSongs.context.tsx @@ -43,38 +43,8 @@ function injectAdSlots( return songsWithAds; } -export const useRecentSongsStore = create((set, get) => ({ - // Initial state - recentSongs: [], - recentError: '', - isLoading: false, - hasMore: true, - selectedCategory: '', - categories: {}, - page: 1, - - // Actions - initialize: (initialRecentSongs) => { - set({ - recentSongs: injectAdSlots(initialRecentSongs), - page: 1, - hasMore: true, - recentError: '', - }); - }, - - fetchCategories: async () => { - try { - const response = await axiosInstance.get>( - '/song/categories', - ); - set({ categories: response.data }); - } catch (error) { - set({ categories: {} }); - } - }, - - fetchRecentSongs: async () => { +export const useRecentSongsStore = create((set, get) => { + const fetchRecentSongs = async () => { const { page, selectedCategory } = get(); set({ isLoading: true }); @@ -114,46 +84,66 @@ export const useRecentSongsStore = create((set, get) => ({ } finally { set({ isLoading: false }); } - }, - - setSelectedCategory: (category) => { - set({ - selectedCategory: category, - page: 1, - recentSongs: Array(pageSize).fill(null), - hasMore: true, - }); - }, - - increasePageRecent: async () => { - const { isLoading, recentError, hasMore, recentSongs } = get(); - - if (isLoading || recentError || !hasMore) { - return; - } + }; + + return { + // Initial state + recentSongs: [], + recentError: '', + isLoading: false, + hasMore: true, + selectedCategory: '', + categories: {}, + page: 1, // Start from page 1 since it's loaded server-side + + // Actions + initialize: (initialRecentSongs) => { + set({ + recentSongs: injectAdSlots(initialRecentSongs), + page: 1, + hasMore: true, + recentError: '', + }); + }, + + fetchCategories: async () => { + try { + const response = await axiosInstance.get>( + '/song/categories', + ); + set({ categories: response.data }); + } catch (error) { + set({ categories: {} }); + } + }, - set({ - recentSongs: [...recentSongs, ...Array(pageSize).fill(null)], - page: get().page + 1, - }); - }, -})); - -// Hook to sync page changes with fetchRecentSongs -export const useRecentSongsPageLoader = () => { - const page = useRecentSongsStore((state) => state.page); - const selectedCategory = useRecentSongsStore( - (state) => state.selectedCategory, - ); - const fetchRecentSongs = useRecentSongsStore( - (state) => state.fetchRecentSongs, - ); + fetchRecentSongs: fetchRecentSongs, - useEffect(() => { - if (page === 1) return; // Skip fetching page 1 as it's already loaded initially - fetchRecentSongs(); - }, [page, selectedCategory, fetchRecentSongs]); -}; + setSelectedCategory: (category) => { + set({ + selectedCategory: category, + page: 1, // Fetch from the first page when category changes + recentSongs: Array(pageSize).fill(null), + hasMore: true, + }); + fetchRecentSongs(); + }, + + increasePageRecent: async () => { + const { isLoading, recentError, hasMore, recentSongs } = get(); + + if (isLoading || recentError || !hasMore) { + return; + } + + set({ + recentSongs: [...recentSongs, ...Array(pageSize).fill(null)], + page: get().page + 1, + }); + fetchRecentSongs(); + }, + }; +}); // Hook to fetch categories on mount export const useRecentSongsCategoriesLoader = () => {