[React Router]<Link> 태그 Issue 해결하기
1. 문제 설명
위의 이미지와 같은 특정 날짜를 기준으로, 주간 박스 오피스 정보를 출력하는 웹 페이지에서
영화 제목을 클릭하면, 해당 영화에 대한 상세 정보가 적힌 웹 페이지로 넘어가는 기능을
React Router를 활용해서 구현하고 정상적으로 동작하는 지 테스트를 해봤다.
'Home.js' (영화 웹 페이지의 기본 화면 담당)
import { useState } from "react";
import { useEffect } from "react";
import Movie from "../Components/Movie";
function Home(){
const [Loading, setLoading] = useState(true);
const [Movies, setMovies] = useState([]);
const getMovies = async() => {
const response = await fetch(
"http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.json?key=3a15c5393ac14d11f6b132d6a07f330c&targetDt=20240131"
);
const json = await response.json();
setMovies(json.boxOfficeResult.weeklyBoxOfficeList);
setLoading(false);
}
useEffect(() => {
getMovies();
}, []);
useEffect(() => {
if(Movies.length === 0){
return;
} else {
console.log(Movies)
}
}, [Movies]);
return (
<div>
{
Loading ? <h3>주간 박스 오피스 데이터를 가져오는 중...</h3>
:<div>
{
Movies.map((movie) => {
return (
<Movie
key={movie.movieCd}
MovieName={movie.movieNm}
openDate={movie.openDt}
AudiCount={movie.audiAcc}
/>);
})}
</div>
}
</div>
);
}
export default Home;
Movie.js (영화 제목 클릭 시, Rendering되는 Component)
function MovieDetail(){
return (
<div>
<h4>Detail</h4>
</div>
);
}
export default MovieDetail;
App.js
import {
BrowserRouter as Router,
Route,
Switch
} from "react-router-dom";
import Home from "./routes/Home";
import MovieDetail from "./routes/MovieDetail";
function App(){
return (
<Router>
<Switch>
<Route path="/movie">
<MovieDetail />
</Route>
<Route exact path="/">
<Home />
</Route>
</Switch>
</Router>
);
}
export default App;
예제를 실행하면 처음 이미지와 같이 주간 박스 오피스 정보가 웹 페이지에 표시되고
이 상태에서 영화 제목을 클릭하면 'Detail'이라고 적힌 웹 페이지로 넘어가져야만 한다.
하지만 실제로 영화 제목을 클릭했을 때, URL은 "/movie"로 변경됐지만, 웹 페이지는 갱신이 안된다.
물론 "/movie" URL을 입력하면 문제없이 잘 넘어가진다.
React-router의 <Link> 태그와 관련된 부분에서 문제가 생겼다고 볼 수 있다.
2. 문제의 원인과 해결 과정
위와 같이 React Router의 <Link> 태그가 정상적으로 작동하지 못하게 된 이유는
현재 사용 중인 'create-react-app'과 'react-router-dom' 5.3 버전이 충돌을 일으켰기 때문이다.
(강의에서 React Router를 설치한 버전과 같은 버전으로 설치하였음)
그리고 이러한 충돌 이슈는 react-router-dom을 최신 버전으로 업데이트해서 손쉽게 해결할 수 있다.
아래 명령어를 입력해서 react-router-dom을 최신 버전으로 업데이트를 진행하였다.
npm install react-router-dom@latest
npm i react-router-dom@latest
react-router-dom이 정상적으로 업데이트 됐는 지를 확인하고 싶다면
'package-lock.json' 파일을 띄우고 그 상태에서 'Ctrl + F 누르면 검색 창을 띄울 수 있다.
'react-router-dom'을 입력하면, 현재 프로젝트 폴더에 설치된 react-router-dom의 버전을 확인할 수 있다.
그리고 추가적으로 react-router-dom 버전 6부터 달라진 점이 있다고 하여
이에 맞춰서 'App.js' 파일의 App 함수 코드도 좀 수정을 해줘야 한다.
('App.js'의 소스코드는 앞 장의 '접은 글'을 참조할 것)
react-router-dom 버전 6부터 <Switch> 태그는 더이상 사용되지 않으며
대신 <Switch> 태그가 수행하던 역할은 <Routes> 태그가 대신 수행하게 된다.
추가적으로 <Routes> 태그가 최적의 경로 배정을 하기 때문에
path 속성의 값과 입력된 URL 값이 정확하게 일치할 때만 하위 요소를 Rendering 시키던
<Route> 태그의 exact 속성도 사용되지 않는다고 한다.
그리고 이제 <Route> Component 사이에 자식 Component를 추가하지 않고
대신에 'element' 속성에 자식 Component를 값으로 전달하도록 바뀌었다.
React Router 공식 문서 참조
import {
BrowserRouter as Router,
Route,
//Switch,
Routes,
} from 'react-router-dom';
import Home from "./routes/Home";
import MovieDetail from "./routes/MovieDetail";
function App(){
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/movie" element={<MovieDetail />} />
</Routes>
</Router>
);
}
export default App;
위와 같이 'App' 함수의 코드를 업데이트하고, 예제에서 영화 제목을 클릭하면
아래와 같이 'Detail'이라고 적힌 웹 페이지로 정상적으로 넘어가지는 것을 확인할 수 있다.
📔 Reference
공식 문서
ReactJS로 영화 웹 서비스 만들기