[FEAT] corect the useMemo and better interface of audio player

This commit is contained in:
Edouard DUPIN 2024-08-26 23:51:53 +02:00
parent 90fb1ed411
commit 53c3cfefe3
15 changed files with 823 additions and 730 deletions

File diff suppressed because it is too large Load Diff

View File

@ -13,14 +13,18 @@ import {
position,
} from '@chakra-ui/react';
import {
MdCheck,
MdFastForward,
MdFastRewind,
MdGraphicEq,
MdLooksOne,
MdNavigateBefore,
MdNavigateNext,
MdOutlinePlayArrow,
MdPause,
MdPlayArrow,
MdRepeat,
MdRepeatOne,
MdStop,
MdTrendingFlat,
} from 'react-icons/md';
@ -29,6 +33,24 @@ import { useActivePlaylistService } from '@/service/ActivePlaylist';
import { useSpecificTrack } from '@/service/Track';
import { DataUrlAccess } from '@/utils/data-url-access';
import { useThemeMode } from '@/utils/theme-tools';
import { isNullOrUndefined } from '@/utils/validator';
export enum PlayMode {
PLAY_ONE,
PLAY_ALL,
PLAY_ONE_LOOP,
PLAY_ALL_LOOP,
};
const playModeIcon = {
[PlayMode.PLAY_ONE]: <MdLooksOne size="30px" />,
[PlayMode.PLAY_ALL]: <MdTrendingFlat size="30px" />,
[PlayMode.PLAY_ONE_LOOP]: <MdRepeatOne size="30px" />,
[PlayMode.PLAY_ALL_LOOP]: <MdRepeat size="30px" />,
};
export type AudioPlayerProps = {};
@ -43,23 +65,18 @@ const formatTime = (time) => {
return '00:00';
};
export const AudioPlayer = ({}: AudioPlayerProps) => {
export const AudioPlayer = ({ }: AudioPlayerProps) => {
const { mode } = useThemeMode();
const { playTrackList, trackOffset, previous, next } =
const { playTrackList, trackOffset, previous, next, first } =
useActivePlaylistService();
const audioRef = useRef<HTMLAudioElement>(null);
const [isPlaying, setIsPlaying] = useState<boolean>(false);
const [timeProgress, setTimeProgress] = useState<number>(0);
const [playingMode, setPlayingMode] = useState<PlayMode>(PlayMode.PLAY_ALL);
const [duration, setDuration] = useState<number>(0);
const { dataTrack, updateTrackId } = useSpecificTrack(
const { dataTrack } = useSpecificTrack(
trackOffset !== undefined ? playTrackList[trackOffset] : undefined
);
useEffect(() => {
console.log(`detect change of playlist ...`);
updateTrackId(
trackOffset !== undefined ? playTrackList[trackOffset] : undefined
);
}, [playTrackList, trackOffset, updateTrackId]);
const [mediaSource, setMediaSource] = useState<string>('');
useEffect(() => {
setMediaSource(
@ -90,7 +107,21 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
}, [isPlaying, audioRef]);
const onAudioEnded = () => {
// TODO...
if (playTrackList.length === 0 || isNullOrUndefined(trackOffset)) {
return;
}
if (playingMode === PlayMode.PLAY_ALL_LOOP) {
if (playTrackList.length == trackOffset + 1) {
first();
} else {
next();
}
} else if (playingMode === PlayMode.PLAY_ALL) {
next();
} else if (playingMode === PlayMode.PLAY_ONE_LOOP) {
onSeek(0);
onPlay();
}
};
const onSeek = (newValue) => {
console.log(`onSeek: ${newValue}`);
@ -138,7 +169,19 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
const onNavigateNext = () => {
next();
};
const onTypePlay = () => {};
const onTypePlay = () => {
setPlayingMode((value: PlayMode) => {
if (value === PlayMode.PLAY_ONE) {
return PlayMode.PLAY_ALL;
} else if (value === PlayMode.PLAY_ALL) {
return PlayMode.PLAY_ONE_LOOP;
} else if (value === PlayMode.PLAY_ONE_LOOP) {
return PlayMode.PLAY_ALL_LOOP;
} else {
return PlayMode.PLAY_ONE;
}
})
};
/**
* Call when meta-data is updated
*/
@ -155,7 +198,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
console.log(`onTimeUpdate ${audioRef.current.currentTime}`);
setTimeProgress(audioRef.current.currentTime);
};
const onDurationChange = (event) => {};
const onDurationChange = (event) => { };
const onChangeStateToPlay = () => {
setIsPlaying(true);
};
@ -277,7 +320,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
<IconButton
{...configButton}
aria-label={'continue to the end'}
icon={<MdTrendingFlat size="30px" />}
icon={playModeIcon[playingMode]}
onClick={onTypePlay}
/>
</Flex>

View File

@ -1,20 +1,23 @@
import { Flex, Text } from '@chakra-ui/react';
import { LuMusic2 } from 'react-icons/lu';
import { LuMusic2, LuPlay } from 'react-icons/lu';
import { Track } from '@/back-api';
import { Covers } from '@/components/Cover';
import { useActivePlaylistService } from '@/service/ActivePlaylist';
export type DisplayTrackProps = {
track: Track;
};
export const DisplayTrack = ({ track }: DisplayTrackProps) => {
const { trackActive } = useActivePlaylistService();
console.log(`Chnage : ${trackActive?.id} == ${track.id}`);
return (
<Flex direction="row" width="full" height="full">
<Covers
data={track?.covers}
size="50"
height="full"
iconEmpty={<LuMusic2 size="50" height="full" />}
iconEmpty={trackActive?.id === track.id ? <LuPlay size="50" height="full" /> : <LuMusic2 size="50" height="full" />}
/>
<Flex
direction="column"
@ -33,6 +36,7 @@ export const DisplayTrack = ({ track }: DisplayTrackProps) => {
overflow="hidden"
noOfLines={[1, 2]}
marginY="auto"
color={trackActive?.id === track.id ? "green.700" : undefined}
>
[{track.track}] {track.name}
</Text>

View File

@ -5,9 +5,9 @@ export const EmptyEnd = () => {
<Box
width="full"
height="25%"
minHeight="25%"
borderWidth="1px"
borderColor="red"
minHeight="250px"
// borderWidth="1px"
// borderColor="red"
></Box>
);
};

View File

@ -24,6 +24,10 @@ export const AlbumDetailPage = () => {
//navigate(`/artist/${artistIdInt}/album/${albumId}`);
let currentPlay = 0;
const listTrackId: number[] = [];
if (!tracksOnAnAlbum) {
console.log("Fail to get album...");
return;
}
for (let iii = 0; iii < tracksOnAnAlbum.length; iii++) {
listTrackId.push(tracksOnAnAlbum[iii].id);
if (tracksOnAnAlbum[iii].id === trackId) {

View File

@ -7,6 +7,7 @@ import { TopBar } from '@/components/TopBar/TopBar';
import { DisplayAlbum } from '@/components/album/DisplayAlbum';
import { useAlbumService } from '@/service/Album';
import { useThemeMode } from '@/utils/theme-tools';
import { EmptyEnd } from '@/components/EmptyEnd';
export const AlbumsPage = () => {
const { store } = useAlbumService();
@ -51,6 +52,7 @@ export const AlbumsPage = () => {
</WrapItem>
))}
</Wrap>
<EmptyEnd />
</PageLayout>
</>
);

View File

@ -27,6 +27,10 @@ export const ArtistAlbumDetailPage = () => {
//navigate(`/artist/${artistIdInt}/album/${albumId}`);
let currentPlay = 0;
const listTrackId: number[] = [];
if (!tracksOnAnAlbum) {
console.error("Fail to get the album ...");
return;
}
for (let iii = 0; iii < tracksOnAnAlbum.length; iii++) {
listTrackId.push(tracksOnAnAlbum[iii].id);
if (tracksOnAnAlbum[iii].id === trackId) {

View File

@ -10,6 +10,7 @@ import { DisplayAlbumId } from '@/components/album/DisplayAlbumId';
import { useSpecificArtist } from '@/service/Artist';
import { useAlbumIdsOfAnArtist } from '@/service/Track';
import { useThemeMode } from '@/utils/theme-tools';
import { EmptyEnd } from '@/components/EmptyEnd';
export const ArtistDetailPage = () => {
const { artistId } = useParams();
@ -83,6 +84,7 @@ export const ArtistDetailPage = () => {
</WrapItem>
))}
</Wrap>
<EmptyEnd />
</PageLayout>
</>
);

View File

@ -8,6 +8,7 @@ import { PageLayout } from '@/components/Layout/PageLayout';
import { TopBar } from '@/components/TopBar/TopBar';
import { useArtistService } from '@/service/Artist';
import { useThemeMode } from '@/utils/theme-tools';
import { EmptyEnd } from '@/components/EmptyEnd';
export const ArtistsPage = () => {
const { mode } = useThemeMode();
@ -70,6 +71,7 @@ export const ArtistsPage = () => {
</WrapItem>
))}
</Wrap>
<EmptyEnd />
</PageLayout>
</>
);

View File

@ -0,0 +1,21 @@
import { Navigate, Route, Routes } from 'react-router-dom';
import { Error404 } from '@/errors';
import { ArtistAlbumDetailPage } from '@/scene/artist/ArtistAlbumDetailPage';
import { ArtistDetailPage } from '@/scene/artist/ArtistDetailPage';
import { ArtistsPage } from '@/scene/artist/ArtistsPage';
export const ArtistRoutes = () => {
return (
<Routes>
<Route path="/" element={<Navigate to="all" replace />} />
<Route path="all" element={<ArtistsPage />} />
<Route path=":artistId" element={<ArtistDetailPage />} />
<Route
path=":artistId/album/:albumId"
element={<ArtistAlbumDetailPage />}
/>
<Route path="*" element={<Error404 />} />
</Routes>
);
};

View File

@ -1,6 +1,8 @@
import { useCallback, useState } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useServiceContext } from '@/service/ServiceContext';
import { TrackServiceProps } from './Track';
import { Track } from '@/back-api';
export type PlaylistElement = {
trackId: number;
@ -9,12 +11,14 @@ export type PlaylistElement = {
export type ActivePlaylistServiceProps = {
playTrackList: number[];
trackOffset?: number;
trackActive?: Track;
setNewPlaylist: (listIds: number[]) => void;
setNewPlaylistShuffle: (listIds: number[]) => void;
playInList: (id: number, listIds: number[]) => void;
play: (id: number) => void;
previous: () => void;
next: () => void;
first: () => void;
};
export const useActivePlaylistService = (): ActivePlaylistServiceProps => {
@ -39,87 +43,102 @@ export function localShuffle<T>(array: T[]): T[] {
return array;
}
export const useActivePlaylistServiceWrapped =
(): ActivePlaylistServiceProps => {
const [playTrackList, setPlayTrackList] = useState<number[]>([]);
const [trackOffset, setTrackOffset] = useState<number | undefined>();
export const useActivePlaylistServiceWrapped = (
track: TrackServiceProps
): ActivePlaylistServiceProps => {
const [playTrackList, setPlayTrackList] = useState<number[]>([]);
const [trackOffset, setTrackOffset] = useState<number | undefined>();
const trackActive = useMemo(() => {
return track.store.get(trackOffset !== undefined ? playTrackList[trackOffset] : undefined);
}, [track.store.data, playTrackList, trackOffset]);
const clear = useCallback(() => {
setPlayTrackList([]);
setTrackOffset(undefined);
}, [setPlayTrackList, setTrackOffset]);
const clear = useCallback(() => {
setPlayTrackList([]);
setTrackOffset(undefined);
}, [setPlayTrackList, setTrackOffset]);
const play = useCallback(
(id: number) => {
setPlayTrackList([id]);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset]
);
const playInList = useCallback(
(id: number, listIds: number[]) => {
console.log(`Request paly in list: ${id} in ${listIds}`);
setPlayTrackList(listIds);
setTrackOffset(id);
},
[setPlayTrackList, setTrackOffset]
);
const play = useCallback(
(id: number) => {
setPlayTrackList([id]);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset]
);
const playInList = useCallback(
(id: number, listIds: number[]) => {
console.log(`Request paly in list: ${id} in ${listIds}`);
setPlayTrackList(listIds);
setTrackOffset(id);
},
[setPlayTrackList, setTrackOffset]
);
const setNewPlaylist = useCallback(
(listIds: number[]) => {
if (listIds.length == 0) {
clear();
return;
}
setPlayTrackList(listIds);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset, clear]
);
const setNewPlaylist = useCallback(
(listIds: number[]) => {
if (listIds.length == 0) {
clear();
return;
}
setPlayTrackList(listIds);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset, clear]
);
const setNewPlaylistShuffle = useCallback(
(listIds: number[]) => {
if (listIds.length == 0) {
clear();
return;
}
const newList = localShuffle(listIds);
setPlayTrackList(newList);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset, clear]
);
const previous = useCallback(() => {
setTrackOffset((previous) => {
if (previous === undefined) {
return previous;
}
if (previous === 0) {
return previous;
}
return previous - 1;
});
}, [setTrackOffset]);
const next = useCallback(() => {
setTrackOffset((previous) => {
if (previous === undefined || playTrackList.length === 0) {
return previous;
}
if (previous >= playTrackList.length - 1) {
return previous;
}
return previous + 1;
});
}, [playTrackList, setTrackOffset]);
const setNewPlaylistShuffle = useCallback(
(listIds: number[]) => {
if (listIds.length == 0) {
clear();
return;
}
const newList = localShuffle(listIds);
setPlayTrackList(newList);
setTrackOffset(0);
},
[setPlayTrackList, setTrackOffset, clear]
);
const previous = useCallback(() => {
setTrackOffset((previous) => {
if (previous === undefined) {
return previous;
}
if (previous === 0) {
return previous;
}
return previous - 1;
});
}, [setTrackOffset]);
const next = useCallback(() => {
setTrackOffset((previous) => {
if (previous === undefined || playTrackList.length === 0) {
return previous;
}
if (previous >= playTrackList.length - 1) {
return previous;
}
return previous + 1;
});
}, [playTrackList, setTrackOffset]);
const first = useCallback(() => {
setTrackOffset((previous) => {
if (previous === undefined || playTrackList.length === 0) {
return previous;
}
return 0;
});
}, [playTrackList, setTrackOffset]);
return {
playTrackList,
trackOffset,
setNewPlaylist,
setNewPlaylistShuffle,
playInList,
play,
previous,
next,
};
return {
playTrackList,
trackOffset,
setNewPlaylist,
setNewPlaylistShuffle,
playInList,
play,
previous,
next,
trackActive,
first,
};
};

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { Album, AlbumResource } from '@/back-api';
import { useServiceContext } from '@/service/ServiceContext';
@ -31,19 +31,17 @@ export const useAlbumServiceWrapped = (
};
export const useSpecificAlbum = (id: number | undefined) => {
const [dataAlbum, setDataAlbum] = useState<Album | undefined>(undefined);
const { store } = useAlbumService();
useEffect(() => {
setDataAlbum(store.get(id));
}, [store.data]);
const dataAlbum = useMemo(() => {
return store.get(id);
}, [store.data, id]);
return { dataAlbum };
};
export const useAlbumOfAnArtist = (idArtist: number | undefined) => {
const [dataAlbum, setDataAlbum] = useState<Album | undefined>(undefined);
const { store } = useAlbumService();
useEffect(() => {
setDataAlbum(store.get(idArtist));
}, [store.data]);
const dataAlbum = useMemo(() => {
return store.get(idArtist);
}, [store.data, idArtist]);
return { dataAlbum };
};

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { Artist, ArtistResource } from '@/back-api';
import { useServiceContext } from '@/service/ServiceContext';
@ -31,10 +31,9 @@ export const useArtistServiceWrapped = (
};
export const useSpecificArtist = (id: number | undefined) => {
const [dataArtist, setDataArtist] = useState<Artist | undefined>(undefined);
const { store } = useArtistService();
useEffect(() => {
setDataArtist(store.get(id));
}, [store.data]);
const dataArtist = useMemo(() => {
return store.get(id);
}, [store.data, id]);
return { dataArtist };
};

View File

@ -25,8 +25,8 @@ export type ServiceContextType = {
export const ServiceContext = createContext<ServiceContextType>({
session: {
setToken: (token: string) => {},
clearToken: () => {},
setToken: (token: string) => { },
clearToken: () => { },
hasReadRight: (part: RightPart) => false,
hasWriteRight: (part: RightPart) => false,
state: SessionState.NO_USER,
@ -36,7 +36,7 @@ export const ServiceContext = createContext<ServiceContextType>({
store: {
data: [],
isLoading: true,
get: (value, key) => undefined,
get: (value, key) => { console.error("!!! WTF !!!"); return undefined; },
error: undefined,
},
},
@ -44,7 +44,7 @@ export const ServiceContext = createContext<ServiceContextType>({
store: {
data: [],
isLoading: true,
get: (value, key) => undefined,
get: (value, key) => { console.error("!!! WTF !!!"); return undefined; },
error: undefined,
},
},
@ -52,17 +52,21 @@ export const ServiceContext = createContext<ServiceContextType>({
store: {
data: [],
isLoading: true,
get: (value, key) => undefined,
get: (value, key) => { console.error("!!! WTF !!!"); return undefined; },
error: undefined,
},
},
activePlaylist: {
playTrackList: [],
trackOffset: undefined,
setNewPlaylist: (listIds: number[]) => {},
setNewPlaylistShuffle: (listIds: number[]) => {},
playInList: (id: number, listIds: number[]) => {},
play: (id: number) => {},
trackActive: undefined,
setNewPlaylist: (_listIds: number[]) => { console.error("!!! WTF !!!"); },
setNewPlaylistShuffle: (_listIds: number[]) => { console.error("!!! WTF !!!"); },
playInList: (_id: number, _listIds: number[]) => { console.error("!!! WTF !!!"); },
play: (_id: number) => { console.error("!!! WTF !!!"); },
previous: () => { console.error("!!! WTF !!!"); },
next: () => { console.error("!!! WTF !!!"); },
first: () => { console.error("!!! WTF !!!"); },
},
});
@ -77,7 +81,7 @@ export const ServiceContextProvider = ({
const track = useTrackServiceWrapped(session);
const artist = useArtistServiceWrapped(session);
const album = useAlbumServiceWrapped(session);
const activePlaylist = useActivePlaylistServiceWrapped();
const activePlaylist = useActivePlaylistServiceWrapped(track);
const contextObjectData = useMemo(
() => ({
session,

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Track, TrackResource } from '@/back-api';
import { useServiceContext } from '@/service/ServiceContext';
@ -33,47 +33,35 @@ export const useTrackServiceWrapped = (
};
export const useSpecificTrack = (id: number | undefined) => {
const [dataTrack, setDataTrack] = useState<Track | undefined>(undefined);
const { store } = useTrackService();
useEffect(() => {
console.log(`retrieve specific track: ${id}`);
setDataTrack(store.get(id));
}, [store.data]);
const updateTrackId = useCallback(
(id: number | undefined) => {
console.log(`retrieve specific track (update): ${id}`);
setDataTrack(store.get(id));
},
[setDataTrack, store]
);
return { dataTrack, updateTrackId };
const dataTrack = useMemo(() => {
return store.get(id);
}, [store.data, id]);
return { dataTrack };
};
/**
* Get all the track for a specific artist
* @param idArtist - Id of the artist.
* @returns a promise on the list of track elements
*/
export const useTracksOfAnArtist = (idArtist?: number) => {
const [tracksOnAnArtist, setTracksOnAnArtist] = useState<Track[]>([]);
const { store } = useTrackService();
useEffect(() => {
const tracksOnAnArtist = useMemo(() => {
if (idArtist) {
setTracksOnAnArtist(
DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
},
],
['track', 'name']
)
);
return DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
},
],
['track', 'name']
)
}
}, [store.data]);
return [];
}, [store.data, idArtist]);
return { tracksOnAnArtist };
};
@ -83,8 +71,8 @@ export const useTracksOfAnArtist = (idArtist?: number) => {
* @returns The number of track present in this artist
*/
export const useCountTracksOfAnArtist = (idArtist: number) => {
const { tracksOnAnArtist } = useTracksOfAnArtist(idArtist);
const countTracksOnAnArtist = tracksOnAnArtist.length;
const { tracksOnAnAlbum } = useTracksOfAnAlbum(idArtist);
const countTracksOnAnArtist = useMemo(() => tracksOnAnAlbum?.length ?? 0, [tracksOnAnAlbum]);
return { countTracksOnAnArtist };
};
@ -94,43 +82,39 @@ export const useCountTracksOfAnArtist = (idArtist: number) => {
* @returns the required List.
*/
export const useAlbumIdsOfAnArtist = (idArtist?: number) => {
const [albumIdsOfAnArtist, setAlbumIdsOfAnArtist] = useState<number[]>([]);
const { tracksOnAnArtist } = useTracksOfAnArtist(idArtist);
useEffect(() => {
const albumIdsOfAnArtist = useMemo(() => {
// extract a single time all value "id" in an array
const listAlbumId = DataTools.extractLimitOne(tracksOnAnArtist, 'albumId');
if (isArrayOf(listAlbumId, isNumber)) {
setAlbumIdsOfAnArtist(listAlbumId);
return listAlbumId;
} else {
console.log(
'Fail to parse the result of the list value (impossible case)'
);
setAlbumIdsOfAnArtist([]);
return [];
}
}, [tracksOnAnArtist]);
return { albumIdsOfAnArtist };
};
export const useTracksOfAnAlbum = (idAlbum?: number) => {
const [tracksOnAnAlbum, setTracksOnAnAlbum] = useState<Track[]>([]);
const { store } = useTrackService();
useEffect(() => {
const tracksOnAnAlbum = useMemo(() => {
if (idAlbum) {
setTracksOnAnAlbum(
DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: idAlbum,
},
],
['track', 'name', 'id']
)
return DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: idAlbum,
},
],
['track', 'name', 'id']
);
}
}, [store.data]);
}, [store.data, idAlbum]);
return { tracksOnAnAlbum };
};
@ -141,7 +125,7 @@ export const useTracksOfAnAlbum = (idAlbum?: number) => {
*/
export const useCountTracksWithAlbumId = (albumId?: number) => {
const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumId);
const countTracksOfAnAlbum = tracksOnAnAlbum.length;
const countTracksOfAnAlbum = useMemo(() => tracksOnAnAlbum?.length ?? 0, [tracksOnAnAlbum]);
return { countTracksOfAnAlbum };
};
@ -151,30 +135,27 @@ export const useCountTracksWithAlbumId = (albumId?: number) => {
* @returns a promise on the list of track elements
*/
export const useTracksOfArtistWithNoAlbum = (idArtist: number) => {
const [tracksOnAnArtistWithNoAlbum, setTracksOnAnArtistWithNoAlbum] =
useState<Track[]>([]);
const { store } = useTrackService();
useEffect(() => {
const tracksOnAnArtistWithNoAlbum = useMemo(() => {
if (idArtist) {
setTracksOnAnArtistWithNoAlbum(
DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
},
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: undefined,
},
],
['track', 'name']
)
return DataTools.getsWhere(
store.data,
[
{
check: TypeCheck.CONTAINS,
key: 'artists',
value: idArtist,
},
{
check: TypeCheck.EQUAL,
key: 'albumId',
value: undefined,
},
],
['track', 'name']
);
}
}, [store.data]);
return [];
}, [store.data, idArtist]);
return { tracksOnAnArtistWithNoAlbum };
};