먼저 프로젝트에서...
영화 포스터를 클릭하면 해당 영화의 id 값(movieId)으로 세부 정보 api를 조회(+해당 영화와 유사한 영화 목록 조회, 해당 영화 리뷰 조회 등)하여 Dynamic Router(동적 라우팅)을 구현하였다.
그런데 문제는 영화 상세 정보 페이지(/detail/[movieId])에서 새로고침을 하면
movieId가 리셋되어 영화 세부 정보 조회 api 등이 호출되지 않는 문제가 발생했다.
해당 문제가 발생한 코드는 다음과 같다.
import {useRouter} from "next/router"
const MovieDetail = () => {
const router = useRouter()
const movieId = router.query.movieId as string
// ... 코드 생략 ...
// url query 변경 시: 세부 정보 -> 유사한 영화 목록 조회
useEffect(() => {
if (movieId !== '') {
fnGetMovieDetail().then(() =>
fnGetSimilarMovie()
)
}
},[movieId])
}
fnGetMovieDetail
과 fnGetSimilarMovie
는 각각 movieId를 parameter로 보내서 api를 조회하는 함수이다.
useEffect 내에서 movieId
를 참조하고 있기 때문에 새로고침을 해도 제대로 동작이 될 거라고 생각했는데 아니었다..
결국 localStorage에 movieId를 저장하여 가져다 써야겠다고 생각하여
코드를 작성해봤지만 원하는대로 동작하는 코드를 작성하기 너무 어려웠다..
해결 코드
수차례 삽질한 결과 새로고침 시 movieId가 제대로 세팅되지 않는 이유는
router.query.movieId 값이 초기 렌더링 시에 설정되지 않았기 때문이었다.
Next.js에서 초기 렌더링 시 movieId가 undefined 상태가 될 수 있다고 한다.
따라서 useEffect
와 useState
를 사용하여 movieId 값이 변경될 때마다 반영되도록 수정하였다.
import {useRouter} from "next/router"
const MovieDetail = () => {
const router = useRouter()
const [movieId, setMovieId] = useState<string>("")
// ... 코드 생략 ...
// url query 변경 감지
useEffect(() => {
if (router.query.movieId) {
setMovieId(router.query.movieId as string)
}
}, [router.query.movieId])
// url query 변경 시: 세부 정보 -> 유사한 영화 목록 조회
useEffect(() => {
if (movieId !== '') {
fnGetMovieDetail().then(() =>
fnGetSimilarMovie()
)
}
},[movieId])
}
→ 먼저 첫 번째 useEffect를 통해 router.query.movieId가 변경되는 것을 감지하고,
해당 값이 변경되면 movieId 상태를 업데이트 한다.
그 후 두 번째 useEffect에서 movieId 상태 변경을 감지하여 영화 데이터들을 정상적으로 가져오도록 처리한다.
이렇게 하면 새로고침을 해도 원하는대로 잘 동작하게 된다!
댓글