2023. 8. 31. 10:51ㆍNext.js/생활코딩

사전 작업
글 수정, 삭제 진행 전 사전 작업을 진행하자.
글을 선택하지 않는 홈에서는 수정, 삭제 버튼이 보이지 않아야 하고, 글을 선택한 후에만 수정, 삭제 버튼이 보여야 한다. 그리고 지금은 업데이트 버튼을 누르면 항상 update/1로 이동하는데, 다이나믹 라우팅도 적용시켜보자.
수정, 삭제 버튼이 글 상세 조회에서만 보이도록 처리
이 부분은 layout.tsx에 children 아래 작성된 ul 태그에 작성되어 있다. 그런데 이 코드를 보였다 안 보였다 하려면 주소의 id가 있는지 없는지 확인해야 한다. 그런데 layout.tsx는 id가 있는지 없는지 확인이 불가능하다.
/src/app/read/[id]/page.tsx는 id 폴더 밑에 있기 때문에 props.params.id를 통해서 접근할 수 있다. 그런데 layout.tsx는 id가 있는 부분 밖에 있는 파일이기 때문에 props로는 params가 주입되지 않는다.
그럼 뭘 써야 할까? useParams api를 쓰면 된다.
https://nextjs.org/docs/app/api-reference/functions/use-params
Functions: useParams | Next.js
Using App Router Features available in /app
nextjs.org
useParams는 클라이언트 컴포넌트 hook이라고 한다. 그런데 우리의 layout.tsx는 서버 컴포넌트다. 그럼 어떻게 layout.tsx에서 useParams를 사용할 수 있을까?
layout.tsx를 전부 클라이언트 컴포넌트로 바꿀 수도 있지만 이렇게 하면 서버 컴포넌트가 제공하는 장점을 잃어버리게 된다. 기본적으로 서버 컴포넌트가 가능하면 서버 컴포넌트를 사용하는 게 유리하다.
그럼 저 클라이언트 컴포넌트가 필요한 부분만 따로 컴포넌트화 시키면 되지않을까? 그런데 같은 파일 안에 있는 특정 함수만 다른 타입의 컴포넌트로 바꿀 수는 없다. 따라서 이걸 별도의 파일로 쪼개보자.
그럼 Controll 파일만 use client를 작성해주고 useParams를 사용해보자. 그럼 이제 글을 상세 조회할 때만 수정, 삭제 버튼이 보이고, 그 외에는 보이지 않는 것을 확인할 수 있다.
// /src/app/Control.tsx
'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/1'>Update</Link>
</li>
<li>
<input type='button' value={'delete'} />
</li>
</>
) : null}
</ul>
);
}
// /src/app/layout.tsx
import Link from 'next/link';
import './globals.css';
import type { Metadata } from 'next';
import { Control } from './Control';
export const metadata: Metadata = {
title: 'Web tutorials',
description: 'Generated by byein',
};
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const resp = await fetch('http://localhost:9999/topics', { cache: 'no-cache' });
const topics = await resp.json();
return (
<html>
<body>
<h1>
<Link href='/'>WEB</Link>
</h1>
<ol>
{topics.map((topic: { id: number; title: string; body: string }) => {
return (
<li key={topic.id}>
<Link href={`/read/${topic.id}`}>{topic.title}</Link>
</li>
);
})}
</ol>
{children}
<Control />
</body>
</html>
);
}
글 수정 버튼 클릭 시 다이나믹 라우팅 적용
그냥 /update/1을 /update/ + id로 변경해주면 된다!
// /src/app/Control.tsx
'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>
);
}
참고자료
생활코딩 - Next.js 13
https://opentutorials.org/course/5098
Next.js 13 - 생활코딩
수업 개요 Next.js는 웹 애플리케이션을 빌드하고 배포하는 데 강력한 도구입니다. 이 도구를 활용하면 모던한 웹 앱을 빠르고 효율적으로 구축할 수 있습니다. 그럼 함께 미래의 웹 개발 패러다
opentutorials.org
Data Fetching: Fetching, Caching, and Revalidating | Next.js
Data fetching is a core part of any application. This page goes through how you can fetch, cache, and revalidate data in React and Next.js. Next.js extends the native fetch Web API to allow you to configure the caching and revalidating behavior for each fe
nextjs.org
'Next.js > 생활코딩' 카테고리의 다른 글
Next.js 13 - 16. 글 삭제 (0) | 2023.08.31 |
---|---|
Next.js 13 - 15. 글수정 (0) | 2023.08.31 |
Next.js 13 - 13 cache (0) | 2023.08.31 |
Next.js 13 - 12. 글생성 (0) | 2023.08.31 |
Next.js 13 - 11. 글 읽기 (0) | 2023.08.31 |