흐름
- (site) ⇒
page.tsx
에서 action을 통해 DB에서 데이터를 바로 가져온후
- PageContent라는 클라이언트 컴포넌트에
songs
라는 데이터를 props
로 넘겨준다.
- 서버 컴포넌트이기 때문에, 직접
createServerComponentClient
를 사용해서 api통신없이 가져올 수 있다.
action
디렉토리를 만들고, getSongs.ts
파일을 만들어 songs테이블에서 전체 데이터를 가져올수있다.
import { Song } from '@/types';
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
const getSongs = async (): Promise<Song[]> => {
const supabase = createServerComponentClient({
cookies: cookies,
});
const { data, error } = await supabase
.from('songs')
.select('*')
.order('created_at', { ascending: false });
if (error) {
console.log(error);
}
return (data as any) || [];
};
export default getSongs;
Page 컴포넌트에서 getSongs라는 액션을 실행한다.
import getSongs from '@/actions/getSongs';
import Header from '@/components/Header';
import ListItem from '@/components/ListItem';
import PageContent from './components/PageContent';
export const revalidate = 0;
export default async function Home() {
// action 실행
const songs = await getSongs();
return (
<div className='bg-neutral-900 rounded-lg h-full w-full overflow-hidden overflow-y-auto'>
<Header>
<div className='mb-2'>
<h1 className='text-white text-3xl font-semibold'>Welcome back</h1>
<div className='grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 mt-4'>
<ListItem
image='/images/liked.png'
name='Liked Songs'
href='liked'
/>
</div>
</div>
</Header>
<div className='mt-2 mb-7 px-6'>
<div className='flex justify-between items-center'>
<h1 className='text-white text-2xl font-semibold'>Newest Songs</h1>
</div>
<PageContent songs={songs} />
</div>
</div>
);
}
PageContent를 거쳐 SongItem이라는 컴포넌트에 song
데이터가 props
로 전달
- SongItem 컴포넌트에서는 이미지를 보여주기위해
useLoadImage
라는 hook을 실행 시킨다.
- useLoadImage의 역할은 song data를 넘겨받아,
supabaseClient
의 storage에 접근하여, 실제 image url을 return 해준다.
import { Song } from '@/types';
import { useSupabaseClient } from '@supabase/auth-helpers-react';
const useLoadImage = (song: Song) => {
const supabaseClient = useSupabaseClient();
// song이 없으면 그냥 null return
if (!song) {
return null;
}
const { data: imageData } = supabaseClient.storage
.from('images')
.getPublicUrl(song.image_path);
return imageData.publicUrl;
};
export default useLoadImage;