Next.js14 정리(1) 이어서…
Parallel Requests
import { Link } from "next/link";
export const metadata = {
title: "Home",
};
export const API_URL = "https://.../movies";
async function getMovies() {
const response = await fetch(API_URL);
const json = await response.json();
return json;
}
export default async function HomePage() {
const movies = await getMovies();
return (
<div>
{movies.map((movie) => (
<li key={movie.id}>
<a href={`movies/${movie.id}`}>{movie.title}</a>
</li>
))}
</div>
);
}
movies/[id]
여러 api 불러올 때 병렬 처리 Promise.all 함수로 불러올 수 있다.
단점 : 모든 api가 불러와져야 화면을 보여준다.
import { API_URL } from "../../../(home)/page";
async function getMovie(id) {
await new Promise((resolve) => setTimeout(resolve, 1000));
const res = await fetch(`${API_URL}/${id}`);
return res.json();
}
async function getVideos(id) {
await new Promise((resolve) => setTimeout(resolve, 1000));
const res = await fetch(`${API_URL}/${id}/videos`);
return res.json();
}
export default async function Movie({ params: { id } }) {
const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]);
return (
<div>
<h1>{movie.title}</h1>
</div>
);
}
Suspense
두 api가 동시에 불러오지만 준비가 먼저 끝난 거는 먼저 보여준다.
⇒ 병렬적으로 2가지를 동시에 fetch할 수 있는데 하지만 하나의 요청이 완료되면 즉시 component가 render 된다.
⇒ 각각 api를 불러오는 컴포넌트로 만들어 개별적으로 기다리게 한다.
Suspense 가 데이터를 fetch 하기 위해 안의 컴포넌트를 await한다.
Suspense 의 fallback 컴포넌트가 await 되는 동안 (fetch 중에)표시할 메세지를 render할 수 있게 해준다.
⭐여기서 이제 데이터 패치를 하지 않기 때문에 ( 각 컴포넌트에서 데이터 패치 ) 형제 페이지인 loading.jsx는 활동하지 않음
//movies/[id]
import { Suspense } from "react";
import MovieInfo from "../../../../components/movie-info";
import MovieVideo from "../../../../components/movie-videos";
export default async function Movie({ params: { id } }) {
return (
<div>
<Suspense fallback={<h1>Loading Info</h1>}>
<MovieInfo id={id} />
</Suspense>
<Suspense fallback={<h1>Loading video</h1>}>
<MovieVideo id={id} />
</Suspense>
</div>
);
}
components/movie-info.jsx
import { API_URL } from "../app/(home)/page";
async function getMovie(id) {
await new Promise((resolve) => setTimeout(resolve, 1000));
const res = await fetch(`${API_URL}/${id}`);
return res.json();
}
export default async function MovieInfo({ id }) {
const movie = await getMovie(id);
return (
<div>
<h6>{JSON.stringify(movie)}</h6>
</div>
);
}
components/movie-videos.jsx
import { API_URL } from "../app/(home)/page";
async function getVideos(id) {
await new Promise((resolve) => setTimeout(resolve, 1000));
const res = await fetch(`${API_URL}/${id}/videos`);
return res.json();
}
export default async function MovieVideo({ id }) {
const videos = await getVideos(id);
return (
<div>
<h6>{JSON.stringify(videos)}</h6>
</div>
);
}
Error Handling
에러가 발생할 경우(ex, 데이터 패치 오류) 보여줄 페이지
movies/[id] 폴더에 error.jsx 파일 생성 ⇒ 해당하는 페이지 옆에 만들어야 한다.
error 컴포넌트에는 "use client" 넣어야 한다.
"use client";
export default function Error() {
return (
<div>
<h1>Error</h1>
</div>
);
}
Dynamic Metadata
async function 처럼 generateMetadata에 params를 받아 올 수 있어 동적 메타데이터를 적용 할 수 있다.
import { Suspense } from "react";
import MovieInfo, { getMovie } from "../../../../components/movie-info";
import MovieVideo from "../../../../components/movie-videos";
export async function generateMetadata({ params: { id } }) {
const movie = await getMovie(id);
return {
title: movie.title,
};
}
export default async function Movie({ params: { id } }) {
return (
<div>
<h3>Detail</h3>
<Suspense fallback={<h1>Loading Info</h1>}>
<MovieInfo id={id} />
</Suspense>
<Suspense fallback={<h1>Loading video</h1>}>
<MovieVideo id={id} />
</Suspense>
</div>
);
}
'Next.js' 카테고리의 다른 글
CSR, SSR, CORS 에러 (2) | 2024.09.02 |
---|---|
Next.js에 mdx파일 적용하기 (0) | 2024.08.30 |
Next.js 14 정리(1) (0) | 2024.08.28 |
Next Auth(2) (0) | 2024.08.26 |
Next Auth(1) (0) | 2024.08.26 |