export default function Page() {
const [isLoading, setIsLoading] = useState(true)
const [movies, setMovies] = useState()
const getMovies = async () => {
const response = await fetch(
'http://url/movies',
)
const json = await response.json()
setMovies(json)
setIsLoading(false)
}
useEffect(() => {
getMovies()
}, [])
return <div>{isLoading ? 'Loading' : JSON.stringify(movies)}</div>
}
fetch는 항상 client 에서 일어난다는 의미state, useState, useEffectexport const metadata = {
title: 'Home',
}
const URL = 'url'
async function getMovies() {
const response = await fetch(URL)
return await response.json()
}
export default async function HomePage() {
const movies = await getMovies()
return <div>{JSON.stringify(movies)}</div>
}
useState, useEffect 는 없다! fetch만 API에 요청한다.
Loading 상태는 있다. 다만 client에서 server로 옮겨졌다.fetch 작업이 끝나지 않으면 UI가 뜨지 않는다이 코드는 사용자에게 전달 되지 않는다. 이는 안전하다는 의미이다.
어떤 데이터는 fetch, api키 사용 db와 통신이 가능
사용자는 여기 있는 코드를 볼 수 없다.
이는 사용자는 fetch가 완료될때 까지 화면을 볼수 없다는 의미이다.
export default function Loading() {
return <h2>Loading...</h2>
}
loading component를 보낸다.fetch등의 작업이 완료 되면 완료된 값을 브라우저에게 보낸다.loading component 대신 결과 값을 렌더링 한다.http streaming으로 nextJS는 페이지를 작은 html 부분으로 나눠서 준비된 부분을 브라우저에게 전달하는 것이다.
import { API_URL } from '../../../(home)/URL'
async function getMovie(id: string) {
const response = await fetch(`${API_URL}/${id}`)
return response.json()
}
async function getVideos(id: string) {
const response = await fetch(`${API_URL}/${id}/videos`)
return response.json()
}
export default async function MovieDetail({
params: { id },
}: {
params: { id: string }
}) {
const movie = await getMovie(id)
const videos = await getVideos(id)
return <h1>{movie.title}</h1>
}
getMovie, getVideosgetMovie가 20초, getVideos가 0.5초가 걸리면getVideos는 20.5초가 소요된다. Promise.all을 이용하면 동시에 fetch 작업이 가능하다.
export default async function MovieDetail({
params: { id },
}: {
params: { id: string }
}) {
const [movie, video] = await Promise.all([getMovie(id), getVideos(id)])
return <h1>{movie.title}</h1>
}
다만 이렇게 진행할경우 fetch작업이 동시에 시작하지만 결국에는 2개의 fetch가 모두 응답받은 뒤에 UI를 확인할 수 있다.
import MovieInfo from '../../../../components/movie-info'
import MovieVideos from '../../../../components/movie-videos'
import { Suspense } from 'react'
export default async function MovieDetail({
params: { id },
}: {
params: { id: string }
}) {
return (
<div>
<Suspense fallback={<h1>Loading movie info</h1>}>
<MovieInfo id={id} />
</Suspense>
<Suspense fallback={<h1>Loading movie videos</h1>}>
<MovieVideos id={id} />
</Suspense>
</div>
)
}
Suspense를 사용하면 각각 로딩할 수 있다.