게으른개발너D
Practice Project 3 - Dynamic Routes 본문
1. Dynamic Routes
Dynamic URL을 어떻게 다루는지 알아보자,
지금까지는 Home과 About 페이지인, / 와 /about 두가지 url이 있다.
영화 상세보기 페이지처럼 url에 변수를 넣는 방법에 대해 알아보려고한다.
create-react-app의 react-router-dom에서는 해당 url은 예를들어 이런식으로 작성한다,
/movies/:id
이렇게 하면 reate-router-dom은 :id 부분이 변수라는 걸 인식한다.
1.1 next.js pages url
next.js에는 router가 없으므로 이런걸 하는 다른 방법이 당연히 존재한다.
pages 디렉토리에서 오직 폴더와 이름가지고만 만들 것이다,
/movies/all 이라는 url을 만들고싶다면 pages 폴더에 movies 폴더를 만든 후 새로운 파일을 만들어, 그 파일 이름은 all.js로 지으면 된다.
/movies 라는 url을 만들고싶다면?
pages 폴더에 movies.js라는 파일을 만들면 된다. 하지만 /movies/all 이라는 url을 가지고 있는 경우가 있기때문에 movies 폴더 안에 index.js 파일을 만들면 된다.
1.2 변수 url
변수를 가지는 url 페이지를 만드는 것 또한 당연히 pages 폴더 안에 만든다.
/movies/:id 라는 url을 만들고 싶다면 movies 폴더 안에 대괄호를 열어 변수를 넣은 이름의 파일을 만들면 된다.
예를들어 movies 안에 [id].js 파일을 만들었다.
// [id].js
import { useRouter } from 'next/router';
export default function Detail() {
const router = useRouter();
console.log(router);
return 'detail';
}
detail 파일을 만들었는데, 여기서 router를 콘솔로 찍으면 어떻게 나오는지 보자.
/movies/654654 로 이동해 보자.
console을 보면 query를 볼 수 있는데, query에는 id가 있고 url에 있는 것과 같다.
2. Movie Detail
2.1 Link
영화 목록을 불러왔던 index.js에서 next/link의 Link를 import 해오고 영화를 Link로 감싸주자.
// index.js
import Link from 'next/link';
function Home({ results }) {
return (
<div className="container">
<Seo title="Home" />
{!results && <h4>Loading..</h4>}
{results?.map((movie) => (
<Link href={`/movies/${movie.id}`} key={movie.id}>
<div className="movie">
<img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
<h4>{movie.original_title}</h4>
</div>
</Link>
))}
</div>
);
}
이제 영화를 클릭하면 아이디에 해당되는 상세보기 페이지로 이동한다.
Link는 영화 제목만 감싸주도록 바꿔주고, 이미지를 클릭했을 때도 상세보기 페이지로 이동하도록 다른 navigating 방법을 알아보자.
2.2 router hook
useRouter를 실행시켜주자.
// index.js
import Link from 'next/link';
import { useRouter } from 'next/router';
function Home({ results }) {
const router = useRouter();
const handleClick = (id) => {
router.push(`/moives/${id}`);
};
return (
<div className="container">
<Seo title="Home" />
{!results && <h4>Loading..</h4>}
{results?.map((movie) => (
<div
onClick={() => handleClick(movie.id)}
className="movie"
key={movie.id}
>
<img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
<h4>
<Link href={`/movies/${movie.id}`}>
{movie.original_title}
</Link>
</h4>
</div>
))}
</div>
);
}
div를 클릭하면 페이지를 이동시킬 handleClick이라는 함수를 만든다.
useRouter를 이용하여 navigating을 하는 방법은 push를 사용하는 것이다.
router.push(이동할 url)
2.3 rewrite
이제 api key를 숨기기 위해서 next.config.js로 가서 rewrite를 하자.
async rewrites() {
return [
{
source: '/api/movies',
destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
},
{
source: '/api/movies/:id',
destination: `https://api.themoviedb.org/3/movie/:id?api_key=${API_KEY}`,
},
];
},
이전에 작성했던 rewrite 바로 밑에 상세보기를 불러올 api 주소를 작성해주면 된다.
중요한건, source에서 :id라고 적었으면 destination에서도 :id라고 적어야한다! 들어가는 변수 명칭을 똑같이 해줘야하는 것!
2.4 push의 다른 기능 (as)
router.push 와 Link를 사용하는 것 말고도 url에 정보를 숨겨서 보내는 방법이 있다.
우리는 url에서 url로 state를 넘겨주는 방법을 공부할 것이다.
그리고 그걸 유저로부터 숨기는 방법도 배울 것이다.
router.push를 할 때 url을 string으로 보낼 수도 있지만 객체로 보내줄 수도 있다.
url은 url이고, as는 필수는 아니지만 as는 브라우저의 url을 마스킹할 것이다.
const handleClick = (id) => {
router.push({
pathname:`/movies/${id}`,
query: {
id,
title: "Potatos"
}
});
};
push 안에 object를 열고 pathname과 query에 위와같이 작성해주었다.
그리고 영화 이미지를 클릭하여 이동하면 해당 movies의 영화 id 경로로 이동한다,
url 뒤쪽에는 위에서 작성해주었던 영화에 대한 정보를 담고있는 query를 확인할 수 있다.
별로 보기 좋지 않으므로 해당 부분을 url에 보이지 않도록 숨길 것이다.
push 인수를 넣는 곳에 콤마를 한 후 as에 관한 인수를 작성해주자.
브라우저에 보일 url을 써준다.
const handleClick = (id) => {
router.push({
pathname: `/movies/${id}`,
query: {
id,
title: 'Potatos',
},
}, `/movies/${id}`);
};
이제 영화 이미지를 클릭하고 해당 페이지로 이동해보면 url은 as 부분에 설정해 놓은 /moives/id 규칙으로 보여진다.
근데 router를 들여다보면 우리가 담아둔 데이터를 확인할 수도 있다!
as로 url을 다르게 보여주자.
const handleClick = (id, title) => {
router.push(
{
pathname: `/movies/${id}`,
query: {
id,
title,
},
},
`/movies/${title}`
);
};
이렇게 하면 url은 /movies/영화제목 으로 보일 것이다.
// [id].js
import { useRouter } from 'next/router';
export default function Detail() {
const router = useRouter();
return (
<div>
<h4>{router.query.title || 'Loading...'}</h4>
</div>
);
}
이렇게하면 query로 넘겨줬던 title을 볼 수 있다.
router.push 말고도 Link 안에서도 같은 기능을 쓸 수 있다. 이런식으로!
<Link
href={{
pathname: `/movies/${movie.id}`,
query: {
title: movie.title,
}
}}
as={`/movies/${movie.title}`}
>
</Link>
3. Catch All
4. 404 Pages
'개발 > NextJS' 카테고리의 다른 글
Practice Project 4 - Catch All and 404 Pages (1) | 2023.12.01 |
---|---|
Practice Project 2 - Server Side Rendering (0) | 2023.11.30 |
Practice Project 1 - Patterns and Redirect, Rewrite (1) | 2023.11.28 |
Framework Overview 3 - Styles and Custom App (1) | 2023.11.23 |
Framework Overview 2 - Static Pre Rendering and Routing (1) | 2023.11.23 |