이번 수업에서는 글을 선택했을 때만 update, delete 기능이 표시되도록 개선을 해보려고 합니다. 이 과정에서 server component에서 client component로 부분적으로 전환하는 방법을 익히게 될 것입니다.
소스코드
https://github.com/egoing/nextapp/commit/66de9dbd93cf1314b486c3ae06c4356940814bb6
절차
1. app/Control.js 생성
"use client" import Link from 'next/link'; import { useParams } from 'next/navigation'; export function Control() { const params = useParams(); const id = params.id; return ( <ul> <li><Link href="/create">Create</Link></li> {id ? <> <li><Link href={"/update/"+id}>Update</Link></li> <li><input type="button" value="delete" /></li> </> : null} </ul> ); }
2. Control 컴포넌트를 app/layout.js에서 사용
import Link from 'next/link' import './globals.css' import { Control } from './Control'; export const metadata = { title: 'Web tutorial', description: 'Generated by egoing', } export default async function RootLayout({ children }) { const resp = await fetch('http://localhost:9999/topics', { cache: 'no-store' }); const topics = await resp.json(); return ( <html> <body> <h1><Link href="/">WEB</Link></h1> <ol> {topics.map((topic)=>{ return <li key={topic.id}><Link href={`/read/${topic.id}`}>{topic.title}</Link></li> })} </ol> {children} <Control /> </body> </html> ) }
server component 내에서는 현재 동적 라우팅의 값([id])을 layout 안에서는 알 수 없습니다. useParams를 사용해야 하는데 useParams는 client component입니다. app/layout.js 전체를 client component로 전환해도 됩니다만, server component의 이점을 포기하기는 싫기 때문에 여기서는 client component의 기능이 필요한 부분만 별도의 컴포넌트로 분리했습니다.