perf(frontend): start playlist data load immediately on selection; useLayoutEffect for faster playlist switch
This commit is contained in:
parent
52953d7e0d
commit
449dfc708e
@ -130,7 +130,8 @@ const RekordboxReader: React.FC = () => {
|
|||||||
loadNextPage,
|
loadNextPage,
|
||||||
searchSongs,
|
searchSongs,
|
||||||
searchQuery,
|
searchQuery,
|
||||||
refresh
|
refresh,
|
||||||
|
switchPlaylistImmediately
|
||||||
} = usePaginatedSongs({ pageSize: 100, playlistName: currentPlaylist });
|
} = usePaginatedSongs({ pageSize: 100, playlistName: currentPlaylist });
|
||||||
|
|
||||||
// Export library to XML
|
// Export library to XML
|
||||||
@ -209,6 +210,10 @@ const RekordboxReader: React.FC = () => {
|
|||||||
// Clear selected song immediately to prevent stale state
|
// Clear selected song immediately to prevent stale state
|
||||||
setSelectedSong(null);
|
setSelectedSong(null);
|
||||||
|
|
||||||
|
// Kick off data load immediately to avoid delay before backend call
|
||||||
|
const target = name || "All Songs";
|
||||||
|
switchPlaylistImmediately(target);
|
||||||
|
|
||||||
// Navigate immediately without any delays
|
// Navigate immediately without any delays
|
||||||
if (name === "All Songs") {
|
if (name === "All Songs") {
|
||||||
navigate("/", { replace: true });
|
navigate("/", { replace: true });
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useLayoutEffect, useCallback, useRef } from 'react';
|
||||||
import { api, type SongsResponse } from '../services/api';
|
import { api, type SongsResponse } from '../services/api';
|
||||||
import type { Song } from '../types/interfaces';
|
import type { Song } from '../types/interfaces';
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Handle playlist changes - streamlined for immediate response
|
// Handle playlist changes - streamlined for immediate response
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (previousPlaylistRef.current !== playlistName) {
|
if (previousPlaylistRef.current !== playlistName) {
|
||||||
// Update refs immediately
|
// Update refs immediately
|
||||||
currentPlaylistRef.current = playlistName;
|
currentPlaylistRef.current = playlistName;
|
||||||
@ -160,6 +160,25 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
|
|||||||
}
|
}
|
||||||
}, [playlistName, initialSearch, loadPage]);
|
}, [playlistName, initialSearch, loadPage]);
|
||||||
|
|
||||||
|
// Imperative method to switch playlist and start loading immediately
|
||||||
|
const switchPlaylistImmediately = useCallback((targetPlaylistName: string) => {
|
||||||
|
// Update refs immediately so effect does not double-trigger
|
||||||
|
currentPlaylistRef.current = targetPlaylistName;
|
||||||
|
previousPlaylistRef.current = targetPlaylistName;
|
||||||
|
currentSearchQueryRef.current = searchQuery;
|
||||||
|
|
||||||
|
// Clear state for instant visual feedback
|
||||||
|
setSongs([]);
|
||||||
|
setTotalSongs(0);
|
||||||
|
setTotalDuration(undefined);
|
||||||
|
setHasMore(true);
|
||||||
|
setCurrentPage(1);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
// Start loading right away
|
||||||
|
loadPage(1, initialSearch, targetPlaylistName);
|
||||||
|
}, [initialSearch, loadPage, searchQuery]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
songs,
|
songs,
|
||||||
loading,
|
loading,
|
||||||
@ -174,5 +193,6 @@ export const usePaginatedSongs = (options: UsePaginatedSongsOptions = {}) => {
|
|||||||
searchSongs,
|
searchSongs,
|
||||||
reset,
|
reset,
|
||||||
refresh: () => loadPage(1)
|
refresh: () => loadPage(1)
|
||||||
|
, switchPlaylistImmediately
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user