React

[NextJS] Route, Routing, Dynamic Routes 사용 방법

cob 2022. 10. 13. 10:03

 

* NextJS 프로젝트 설치 및 실행 *
https://cocococo.tistory.com/42

* Source Code *
https://github.com/kangilbin/React.js/tree/master/nextjs-study

 

 


1. Routes

pages 폴더 안에 새로운 page 파일을 넣게 되면 자동으로 이동할 수 있다.

page 추가

( about.tsx )


  
export default function Potato() {
return "about";
}
  • export default로 만들어 주어야한다.
  • 함수명은 상관없다.

page url

  • 파일 이름이 그대로 url로 들어간다.
  • index 파일은 메인 홈페이와 연결되어있다. http://localhost:3000  => index 페이지

 

 


2. Routing


  
import Link from "next/link";
export default function NavBar() {
return (
<nav>
<Link href="/"><a className="hello" style={{color:black}}>Home</a></Link>
<Link href="/about"><a>About</a></Link>
</nav>
);
};
  • 따로 Router 라이브러리를 설치하지 않아도 작동한다.
  • Routing 하는데 <a /> 태그를 사용할 수 없고, Link태그를 사용해야 한다.

  
// <a />태그만 단독 사용 x
<a href='URL'>About</a>
// Link 내부에 <a />
<Link href="/about"><a>About</a></Link>
  • 새로고침 할 경우 페이지 전체를 렌더링 하지 않기 위해 NextJS에서 라우팅 시에 사용해야 하는 방법이(Link 컴포넌트) 존재한다.

 

 

2-1) Props 전달


  
import Link from "next/link";
export default function NavBar() {
return (
<nav>
<Link href="/"><a className="hello" style={{color:black}}>Home</a></Link>
</nav>
);
};
  • Prop을 주기 위해서 <Link /> 안에 <a />를 사용하여 <a /> 태그에 Prop 값을 전달해 준다.

 

 

2-2) useRouter Hook ( URL 정보)

useRouter Hook은 location에 관한 정보를 가지고 있다. asPath, back, basePath 등

  
import Link from "next/link";
import { useRouter } from "next/router";
export default function NavBar() {
const router = useRouter();
return (
<nav>
<Link href="/">
<a style={{color: router.pathname === "/" ? "red" : "blue"}}>Home</a>
</Link>
<Link href="/about">
<a style={{color: router.pathname === "/abount" ? "red" : "blue"}}>About</a>
</Link>
</nav>
);
};
  • pathname에 페이지 url를 가지고 있다.

 

 

 


3. Dynamic Routes (동적 라우트)

page 추가

  • 패키지 경로url 경로와 맵핑해 준다.
* http://{URL} / {패키지 경로}  *
http://localhost:3000/movies/all

 

3-1) 서브 경로의 index 페이지 설정

패키지 index 페이지

  • /moves 주소와 하위 주소까지 가지고 싶다면 moves 폴더 안에 index 이름으로 파일을 만든다.
    ( http://localhost:3000/movies => index 페이지)

 

 

3-2) 변수를 포함하는 Dynamic URL 

Dynamic URL

  • 파일명을 대괄호([]) 만들면 Dynamic URL이라고 알려준다.
  • 파일명([id])과 전달받은 파라미터 변수명이 같아야 한다.
* http://{url}/movies/:id *
ex) http://localhost:3000/movies/539681

 

(URL 객체로 페이지 이동)


  
import { useRouter } from 'next/router'
export default function ReadMore({ post }) {
const router = useRouter()
return (
<button
type="button"
onClick={() => {
router.push({
pathname: '/movies/[id]',
query: { id: post.id },
})
}}
>
Click here to read more
</button>
)
}

 

( [id].tsx )


  
import { useRouter } from "next/router";
export default function Detail(){
const route = useRouter();
console.log(route)
return "detail";
}
  • 함수명은 상관없다.

Route Obejct

  • 파라미터는 route Object의 query안에 있다. key값은 대괄호 안에 있는 파일명이랑 동일하다.

 

 

3-3) Navigating 방법 예


  
import Seo from "./../components/Seo";
import Link from "next/link";
import { useRouter } from "next/router";
interface IMoviProp {
id: number;
original_title: string;
poster_path: string;
}
export default function Home({ results }: { results: IMoviProp[] }) {
const router = useRouter();
const onClick = (id: number) => {
router.push(`/movies/${id}`);
};
return (
<div>
<Seo title="Home" />
{results?.map((movie) => (
<div onClick={() => onClick(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}`}>
<a>{movie.original_title} </a>
</Link>
</h4>
</div>
))}
</div>
);
}

 

( 마스킹 처리(as) url로 state 넘겨주는 방법 )


  
<Link
href={{
pathname: `/movies/${movie.id}`,
query: {
id,
title: "potatos",
},
}}
as={`/movies/${movie.id}`}
>
<a>{movie.original_title} </a>
</Link>

 

( 이벤트를 사용한 url로 state 넘겨주는 방법 )


  
const router = useRouter();
const onClick = (id: number) => {
router.push({
pathname: `/movies/${id}`,
query: {
id,
title: "potatos",
},
});
};

event로 parameter 넘겨주기

(이벤트를 사용한 url 마스킹 처리 방법 )


  
const onClick = (id: number) => {
router.push(
{
pathname: `/movies/${id}`,
query: {
title: "potatos",
},
},
// 마스킹하고 싶은 url 입력
`/movies/${id}`
);
};

 

 

3-4) catch-all URL

뭐든 무한대로 잡아내는 url이다.

catch all
url 경로

  • […id] : 파일명(파일명은 상관없음) 앞에 … 을 주게 되면 모든 주소에 접근할 수 있다.

catch all param

  • query값이 배열로 변경된다.

 

( [...params].tsx param 가져오기 )


  
import { NextRouter, useRouter } from "next/router";
// Obejct가 아니기 때문에 type으로 선언문으로 배열값의 type을 지정해준다.
type routerParam = [string, string];
export default function Detail() {
const router: NextRouter = useRouter();
// 최초 렌더링시 HTML 파일만 내려오기 때문에 useRouter 값을 제대로 불러오지 못한다 그렇기 때문에 초기에 빈배열 추가해준다.
const [title, id] = (router.query.params || []) as routerParam;
return (
<div>
<h4>{title}</h4>
</div>
);
}
  • 초기값 빈 배열을 설정해 주어야 한다.

 

 

3-5) SSR (Server Side Rendering)로 백엔드에서 받아온 param 정보를 넘겨주는 방법.

* 공식 문서 *
https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#getserversideprops-with-typescript

  
import { GetServerSideProps, InferGetServerSidePropsType } from "next";
import { NextRouter, useRouter } from "next/router";
import { ParsedUrlQuery } from "querystring";
type routerParam = [string, string];
export default function Detail({
params,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
const [title, id] = (params || []) as routerParam;
return (
<div>
<h4>{title}</h4>
</div>
);
}
interface IServerParams extends ParsedUrlQuery {
params: string;
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const params = context.params as IServerParams;
return {
props: params,
};
};
  • API 요청이 아닌 단순 페이지 이동이기 때문에 느려질 가능성은 거의 없다.
반응형