getSongByTitle
action이 핵심 로직
import { Song } from '@/types';
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import getSongs from './getSongs';
const getSongsByTitle = async (title: string): Promise<Song[]> => {
const supabase = createServerComponentClient({
cookies: cookies,
});
// 타이틀이 따로 없다면 걍 전체 노래 가져온다
if (!title) {
const allSongs = await getSongs();
return allSongs;
}
const { data, error } = await supabase
.from('songs')
.select('*')
.ilike('title', `%${title}%`)
.order('created_at', { ascending: false });
if (error) {
console.log(error);
}
return (data as any) || [];
};
export default getSongsByTitle;
SearchInput이 존재하는데 하는 역할
async function SearchPage({ searchParams }: SearchProps) {
// SearchInput에서 넘긴 query를 action에 넘긴다.
const songs = await getSongsByTitle(searchParams.title);
return (
<div className='bg-neutral-900 roundded-lg w-full h-full overflow-hidden overflow-y-auto'>
<Header className='from-bg-neutral-900'>
<div className='mb-2 flex flex-col gap-y-6'>
<h1 className='text-white text-3xl font-semibold'>Search</h1>
<SearchInput />
</div>
</Header>
<SearchContent songs={songs} />
{/* TODO : Add Like Button Here */}
</div>
);
}
page.tsx ⇒ SearchContent.tsx
search ⇒ page.tsx
는 서버컴포넌트이기 때문에 songs가 터미널에 출력이 된다\
search ⇒ page.tsx
⇒ SearchContent.tsx
는 클라이언트 컴포넌트이기 때문에, 실제 브라우저에서 콘솔이 찍힌다.
<aside> 💡 서버 컴포넌트와 클라이언트 컴포넌트 어디서 어떤걸 찍을지 확인을 해본다!
</aside>