본문 바로가기
프로젝트 기록

[Next.js] router.query 사용 시 초기 렌더링 값 설정하기 (새로고침 오류 해결)

by dygreen 2023. 5. 26.

먼저 프로젝트에서...

영화 포스터를 클릭하면 해당 영화의 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])

}

fnGetMovieDetailfnGetSimilarMovie는 각각 movieId를 parameter로 보내서 api를 조회하는 함수이다.

 

useEffect 내에서 movieId를 참조하고 있기 때문에 새로고침을 해도 제대로 동작이 될 거라고 생각했는데 아니었다..

결국 localStorage에 movieId를 저장하여 가져다 써야겠다고 생각하여

코드를 작성해봤지만 원하는대로 동작하는 코드를 작성하기 너무 어려웠다..

 


해결 코드 

수차례 삽질한 결과 새로고침 시 movieId가 제대로 세팅되지 않는 이유는

router.query.movieId 값이 초기 렌더링 시에 설정되지 않았기 때문이었다.

Next.js에서 초기 렌더링 시 movieId가 undefined 상태가 될 수 있다고 한다.

 

따라서 useEffectuseState를 사용하여 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 상태 변경을 감지하여 영화 데이터들을 정상적으로 가져오도록 처리한다.

이렇게 하면 새로고침을 해도 원하는대로 잘 동작하게 된다!

 

 

728x90

댓글