저번시간 작성했던 accessToken은 개인플레이리스트까지 접근할 수 없는 token이라 새로 accessToken을 구하는 로직을 작성했다.
src > utils > playlistApi.ts
export const recommandPlaylist = async (offset = 0, limit = 20) => {
const accessToken = await getAccessToken();
const res = await axios.get(`${BASEURL}/browse/featured-playlists`, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json"
},
params: {
offset: offset,
limit: limit
}
});
return res.data.playlists;
};
플레이리스트를 나타내는 로직은 저번에 작성했던 accessToken을 가져오는 방법으로 접근이 가능한 api였고 나를 제외한 다른 팀원들은 기본 accessToken을 사용하여 팀원분의 로직을 호출해 넣어주었다.
spotify developer 에서 하는 방법을 자세히 알려주고 있었다.
src > components > RecommendPlaylist.tsx
const RecommendPlaylist = ({ onPlaylistSelect }: RecommendPlaylistProps) => {
const [offset, setOffset] = useState(0);
const limit = 5;
tanstackQuery를 사용하여 상태를 관리하고 있었음으로 queryKey에 offset값을 추가해주었다.
=> React Query는 queryKey를 기준으로 캐시를 관리한다.
offset값을 querykey에 포함하지 않으면 서로 다른 페이지의 데이터가 동일한 캐시로 처리될 수 있다. 이로 인해 캐시가 덮여쓰여지거나 잘못된 데이터가 들어올 수 있음으로 querykey에 offset값을 넣음
페이지에 버튼을 만들어주고 이전 버튼과 다음 버튼에 넣을 로직을 작성해주었다.
// 다음 페이지로 이동하는 함수
const handleNextPage = () => {
if (playlists.items.length === limit) {
setOffset((prev) => prev + limit);
}
};
// 이전 페이지로 이동하는 함수
const handlePrevPage = () => {
setOffset((prev) => Math.max(0, prev - limit));
};
<button onClick={handleNextPage} disabled={playlists.items.length < limit} className="bg-gray-300 rounded p-2">
다음
</button>
src > utils > playlistApi.ts
지난 번에는 일반 accessToken으로 연결했던 부분을 supabase.session을 통해 가져온 provider 로직으로 변경해주었다.
// 내 플레이리스트 불러오기
export const fetchPlaylist = async (offset = 0, limit = 20) => {
const accessToken = await getPrivateAccessToken();
const res = await axios.get(`${BASEURL}/me/playlists`, {
headers: {
Authorization: `Bearer ${accessToken}`
},
params: {
offset: offset,
limit: limit
}
});
return res.data;
};
🥵 문제점
✨ 해결방법
내가 생각한 레이아웃은 왼쪽에 선택한 플레이리스트의 재생목록이 나오고 내 플레이리스트를 선택했을 시에는 오른쪽의 검색칸에서 곡을 추가하고 리스트에서 곡이 삭제도 가능하게 만드는 것이었다. 오른쪽에 있는 추천 플레이리스트, 내 플레이리스트를 클릭했을 때 곡들이 나와야하기 때문에
playlist.tsx 페이지 에서
props로 이벤트 전달을 받았다.
const PlaylistPage = () => {
const [selectedPlaylist, setSelectedPlaylist] = useState<string | null>(null);
// 플레이리스트 선택 핸들러
const onPlaylistSelect = (id: string | null) => {
console.log("Selected Playlist ID:", id);
setSelectedPlaylist(id);
};
<section className="w-[95%] mx-auto flex">
<article className="w-[30%] bg-white p-7 flex-grow min-h-[700px]">
<SongList playlistId={selectedPlaylist} />
</article>
<article className="w-[70%] min-h-[80vh] bg-white p-7 flex flex-col justify-between flex-grow gap-3">
<div className="flex-1">
<SearchSong />
</div>
<div className="flex-1">
<MyPlaylist onPlaylistSelect={onPlaylistSelect} />
</div>
<div className="flex-1">
<RecommendPlaylist onPlaylistSelect={onPlaylistSelect} />
</div>
</article>
</section>
<ul className="w-[90%] flex list-none gap-4 justify-start">
{playlists.items.map((playlist) => (
<li key={playlist.id} onClick={() => onPlaylistSelect(playlist.id)} className="cursor-pointer">
<PlaylistCard playlist={playlist} />
</li>
))}
</ul>
src > component > SongList.tsx
const {
data: playlistData,
isLoading,
error
} = useQuery<PlaylistData>({
queryKey: ["songList", playlistId],
queryFn: () => fetchSongsByPlaylist(playlistId!),
enabled: !!playlistId
});
💥 문제점
✨ 해결방법
export interface Track {
id: string;
name: string;
album: AlbumList;
artists: ArtistList[];
external_urls: {
spotify: string;
};
}
export interface TrackList {
track: Track;
}
export interface PlaylistData {
name: string;
tracks: {
items: TrackList[];
};
}
점점 Next.js에서 제공하는 app router방식의 routing방식이 익숙해지고 tanstackquery를 사용해 데이터를 가져오고 저장하는 방식이 익숙해지는 것 같다. 처음에는 zustand, context, tanstackquery 하나하나 사용방법 , 이용용도가 많이 헷갈렸는데 그래도 지금은 최소한의 기준을 점점 높여가고 있는 것 같다...!
하나의 트러블 슛팅에 주말내내 월요일인 오늘까지도 정말 많은 시간을 보냈는데 나중엔 휙휙 해결해 나갈 수 있는 내가 될 수 있기를