Next에서 페이지를 전환하면서 간단하게 데이터를 전송하는 방법을 알아보려고 합니다.
대표적으로 두가지 방법이 존재합니다 Link 태그를 이용하는 방법과 router객체를 이용하는 방법입니다.
Next 에서 클라이언트 사이드에서 경로간의 이동은 Link컴포넌트를 통해 이루어질 수 있다.
Link
는 다음과 같은 props를 허용
- href - 이동할 경로 혹은 URL. 유일한 필수 prop. (필수이기 때문에 href를 안 적으면 에러난다)
- as - 브라우저 URL 표시 줄에 표시 될 경로에 대한 선택적 데코레이터. Next.js 9.5.3 이전에는 동적 경로에 사용되었으므로 이전 문서 에서 작동 방식을 확인하길 바란다.
- passHref - href property를 Link 자식에게 강제로 전달하게 한다. 기본값은 false.
- prefetch - 백그라운드에서 페이지를 미리 가져온다. 기본값은 true. 뷰 포트에 있는 모든 항목(초기에 혹은 스크롤을 통해)이 미리 로드 된다. prefetch={false}를 통해 프리페치를 비활성화할 수 있다. 정적 생성을 사용하는 페이지는 더 빠른 페이지 전환을 위해 데이터가 포함된 JSON파일을 미리 로드한다.
- replace - history 스택(방문 기록)에 새 url을 추가하는 대신 현재 상태를 변경한다. 기본값은 false
- scroll - 페이지 전환 후 페이지 상단으로 스크롤할지 여부. 기본값은 true.
- shallow - getStaticProps, getServerSideProps, getInitialProps을 다시 실행하지 않고 현재 경로를 업데이트. 기본값은 false.
정말 다양한 props들이 있는데 이번에는 데이터를 가지고 이동하는 방법을 알아보는 것이니 href, as
를 중심으로 알아보자
import Link from 'next/link'
function Posts({ posts }) {
return (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>
<a>{post.title}</a>
</Link>
</li>
))}
)
}
export default Posts
해당 코드는 데이터를 별도로 가지고 보내지않는 일반적인 Link 사용법이다,
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link
href={{
pathname: '/about',
query: { name: 'test' },
}}
>
<a>About us</a>
</Link>
</li>
<li>
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: 'my-post' },
}}
>
<a>Blog Post</a>
</Link>
</li>
</ul>
)
}
export default Home
위에 query에 담아서 이동을 할 수 있다.
위의 예는 다음 링크를 가진다:
/about?name=test
/blog/my-post
하지만 이렇게되면 사용자 url에 query에 데이터가 전부 노출된다.
그리고 또한 보내고 싶은 data가 Object형태일 경우 string으로 변환을 해주어야한다. 이를 JSON.stringify를 사용해서 변환할 수 있는데 그러면 URL의 길이가 어마해진다.
그러므로 해결을 위해 as props를 추가해서 방지해주자
import Link from 'next/link'
//생략
<Link
href={{
pathname: '/about/question/[name]',
query: { post: JSON.stringify(post) },
}}
as={`/about/question/${post.name}`}
>
<a>About us</a>
</Link>
//생략
export default Home
as는 간단하게 Route Masking
으로 표현할 수 있다.
이번에는 경로 정보를 담고 있는 라우터 객체를 한번 살펴보도록 하겠습니다.
라우터 객체는 next/router 모듈에서 useRouter 훅을 불러와 사용할 수 있습니다.
import { useRouter } from 'next/router';
export default function Home() {
const router = useRouter();
console.log(router);
// ...
}
router 를 콘솔로 찍어보면 아래와 같은 객체가 나타난다.
- asPath - string - basePath 또는 locale 없이 브라우저에 표시되는 경로 (쿼리포함)
- basePath - string - 활성 basePath (활성화 된 경우)
- defaultLocale - string - 현재 기본 locale (활성화 된 경우)
- isFallback - boolean - 현재 페이지가 fallback 모드인지 여부
- isPreview - boolean - 앱이 현재 미리보기 모드인지 여부
- isReady - boolean - 라우터 필드가 클라이언트 측에서 업데이트되고 사용할 준비가 되었는지 여부. useEffect 메소드 내에서만 사용해야하며 서버에서 조건부로 렌더링 하는 데에 사용해야한다.
- locale - string - 활성 로케일 (활성화 된 경우)
- locales - string[] - 지원되는 모든 로케일 (활성화 된 경우)
- pathname - string - 현재 경로. 이는 /pages 의 페이지 경로이며(파일명) 구성된 basePath 또는 locale 은 포함되지 않는다.
- query - object - 객체로 구문 분석 된 쿼리 문자열. 페이지에 데이터 가져오기 요구사항이 없는 경우 사전 렌더링 중에 빈 객체가 된다. 기본값은 {}
⇒ 동적 라우팅 사용시 쿼리값이 객체로 들어감.
router에 메서드도 어마하게 많지만 데이터 전송하는 방법만을 다루겠습니다.
💡 클라이언트 사이드 라우팅을 처리한다. next/link 로 충분하지 않은 경우에 유용하다.
router.push(url, as, options)
- url - 이동할 경로
- as - 브라우저에 표시될 URL에 대한 선택적 데코레이터.
- options - 다음 구성 옵션이 있는 선택적 객체
- scroll - 기본 값은 true. 선택 boolean. 이동 후 페이지를 상단으로 스크롤 제어.
- shallow - 기본 값은 false. getStaticProps, getServerSideProps 또는 getInitialProps 를 다시 실행하지 않고 현재 페이지의 경로를 업데이트.
- locale - 선택적 문자열. 새 페이지의 로케일을 나타낸다.
import { useRouter } from 'next/router';
export default function Page() {
const router = useRouter();
return (
<button type="button" onClick={() => router.push('/about')}>
Click me
</button>
)
💡 next/link 에서 사용한 것처럼 URL 객체를 사용할 수 있다.
import { useRouter } from 'next/router'
export default function ReadMore({ post }) {
const router = useRouter()
return (
<button
type="button"
onClick={() => {
router.push({
pathname: '/post/[pid]',
query: { pid: post.id },
},
"/order"
)
}}
>
Click here to read more
</button>
)
}
두번째 인자로 마스킹까지 해주었다.
개인적으로 Link는 클릭 시 별도의 동작이 필요없고 넘겨주기만 하면될 때 저렇게 Link사용하며,
클릭 시 부가적인 함수나 동작이 실행되고 페이지넘겨줘야할 때 router.push를 사용한다
Link 공식문서
https://kimsangyeon-github-io.vercel.app/blog/2021-07-28-nextjs-router
자세한 글 감사합니다~ 도움이 되었습니다.
[slug] 컴포넌트에서 query 꺼내쓰는 방법도 알고 싶어요