티스토리 뷰
Router
redirect 기능처럼 컴포넌트에서 버튼을 클릭해서 동적 라우팅을 구현할 수 있다. 참고로 app 내부의 컴포넌트는 서버 컴포넌트 이기 때문에 사용자가 클릭해서 클라이언트 라우팅을 시키려면 버튼 컴포넌트는 따로 클라이언트 컴포넌트로 빼줘야 한다.
예시 코드
products 상세페이지 서버 컴포넌트
src/app/products/[item]/page.tsx
import { Metadata } from "next";
import React from "react";
import { typesOfItem } from "@/app/shared/const";
import { getProduct } from "@/service/products";
import { notFound, redirect } from "next/navigation";
import Image from "next/image";
import GoProductsBtn from "@/components/GoProductsBtn";
type Props = {
params: {
item: string;
};
};
export const revalidate = 3;
export function generateMetadata({ params: { item } }: Props): Metadata {
return {
title: `제품의 이름: ${item}`,
};
}
export default async function ProductItemDetailPage({
params: { item },
}: Props) {
const product = await getProduct(item);
if (!product) {
redirect("/products");
}
//서버 파일에 있는 데이터 중 해당 제품의 정보를 찾아서 그걸 보여준다.
return (
<>
<div>{product.name} DetailPage</div>
<Image
src={`/images/${product.imageUrl}`}
alt={product.name}
width={300}
height={300}
/>
<GoProductsBtn />
</>
);
}
// 모든 제품의 디테일 페이지를 미리 만들어둠(SSG)
//? generateStaticParams도 비동기 함수처리 가능
export async function generateStaticParams() {
return typesOfItem.map((itemName) => ({ item: itemName }));
}
- SPA 방식에 익숙해져서 GoProductsBtn 부분을 <button onClick ~ > 이런 식으로 작성했었는데 클라이언트에서 동적 라우팅 시키는 것이라는 사실을 염두하면 따로 클라이언트 컴포넌트로 빼주는 게 맞다.
src/components/GoProductsBtn.tsx
"use client";
import { useRouter } from "next/navigation";
import React from "react";
export default function GoProductsBtn() {
const router = useRouter();
return (
<button
onClick={() => {
router.push("/products");
}}
>
제품 페이지로 이동
</button>
);
}
- 여기서 onClick 이벤트를 처리해주는데 useRouter 이라는 함수를 next/navigation 에서 import해온다.
Q. useRouter 가 2개인데 어느 객체에서 import 해와야 하나요?
참고로 12버전 pages 기반에서는 next/router 에서 import 해왔다.
(버전마다 임포트 해오는 객체가 다르니 잘 보고 가져와야 한다.)
- 13버전(app기반): import { useRouter } from "next/navigation";
- 12버전(pages기반): import { useRouter } from "next/router";
Next 이미지 컨텐츠 최적화 오류
에러 메세지
warn-once.js:16 Image with src "/_next/static/media/clothes.08a4a46d.jpg" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.
내용: 큰 이미지 컨텐츠가 최적화가되지 않고 동작하고 있다는 뜻
해결방법: priority 속성을 줘서 lazy load를 비활성화 시키고 우선순위를 높여 pre-load시킨다.
- priority={true} 혹은 priority 만 주면 된다.(기본값이 false)
//코드 중략
return (
<>
<div>{product.name} DetailPage</div>
<Image
priority={true}
src={`/images/${product.imageUrl}`}
alt={product.name}
width={300}
height={300}
/>
<GoProductsBtn />
</>
);
}
ref: https://nextjs.org/docs/pages/api-reference/components/image#priority
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 항해99프론트
- && 셸 명령어
- reactAPI
- grid flex
- tilde caret
- 타입스크립트 DT
- 항해99추천비추천
- aspect-ratio
- Prittier
- 원티드 프리온보딩 프론트엔드 챌린지 3일차
- 원티드 3월 프론트엔드 챌린지
- fs모듈 넥스트
- 항해99프론트후기
- is()
- D 플래그
- float 레이아웃
- getServerSideProps
- nvm 설치순서
- text input pattern
- ~ ^
- 틸드와 캐럿
- nvm경로 오류
- 부트캠프항해
- getStaticPaths
- 원티드 FE 프리온보딩 챌린지
- 타입스크립트 장점
- 원티드 프리온보딩 FE 챌린지
- 프리렌더링확인법
- 형제 요소 선택자
- 프리온보딩 프론트엔드 챌린지 3월
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함