넥스트 ^v13.* App 디렉토리를 사용하게 되는 경우 기존 Page 디렉토리에서 사용하던 next/router 를 사용하지 않고 next/navigation을 통해 사용할 수 있게 변경되었다
pageDir:
import { useRouter } from 'next/router'
appDir:
import {
useRouter,
usePathname,
useSearchParams,
useSelectedLayoutSegment,
useSelectedLayoutSegments,
redirect,
notFound
} from 'next/navigation'
useRouter'use client'필수 next/router에서 사용하던 일부 함수만 사용 가능하며 추가적인 기능도 있다useRouter` 함수
push(href: string) :href 로 클라이언트 사이드 내비게이션next/router 의 as, options 사용 불가replace(href: string) :href 로 클라이언트 사이드 내비게이션next/router 의 as, options 사용 불가refresh() :prefetch(href: string)href에 대한 페이지 prefetch 하여 더욱 빠른 클라이언트 사이드 페이지 전환을 구현할 수 있다next/link의 prefetch와 같은 기능을 직접 trigger 할 수 있다는 장점이 있다back(), forward()usePathname'use client'필수 usage:
'use client'
import { usePathname } from 'next/navigation'
const Component = () => {
const pathname = usePathname()
...
}
| URL | Returned value |
|---|---|
/ | / |
/posts | /posts |
/posts?k=v | /posts |
/posts/some-post | /posts/some-post |
useSearchParams'use client'필수 read-only 버젼을 반환usage:
'use client'
import { useSearchParams } from 'next/navigation'
const Component = () => {
const searchParams = useSearchParams()
const searchTerm = searchParams.get('searchTerm')
...
}
| URL | searchParams.get('seachTerm') |
|---|---|
/posts?searchTerm=test | test |
useSearchParams 함수
getAll(name: string) :string[]keys() :string[]values() :string[]entries()Array<[key: string, value: string | string[]]>forEach()Array<string>toString()useSelectedLayoutSegment'use client'필수 active 한 segment의 값을 (/ 가 포함되지 않은) 반환Header Footer와 같이 글로벌하게 사용되는 레이아웃 컴포넌트에서 이를 활용하여 조건부 처리가 가능하다usage:
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
interface Params {
slug: string
children: ReactNode
}
const Component = ({ slug, children } : Params) => {
const segments = useSelectedLayoutSegment()
const isActive = slug === segment
return (
<Link
href={`/posts/${slug}`}
style={{ fontWeight: isActive ? 'bold' : 'normal' }}
>
{children}
</Link>
)
}
| Layout | Visited URL | Returned segment |
|---|---|---|
app/layout.js | / | null |
app/layout.js | /posts | posts |
app/posts/layout.js | /posts | null |
app/posts/layout.js | /posts/some-post | posts |
app/posts/layout.js | posts/some-post/edit | edit |
useSelectedLayoutSegments'use client'필수 active 한 segment의 값을 (/ 가 포함되지 않은) 문자열 배열로 반환usage:
'use client'
import { useSelectedLayoutSegmentㄴ } from 'next/navigation'
interface Params {
slug: string
children: ReactNode
}
const Component = ({ slug, children } : Params) => {
const segments = useSelectedLayoutSegments()
...
}
| Layout | Visited URL | Returned segment |
|---|---|---|
app/layout.js | / | [] |
app/layout.js | /posts | [posts] |
app/layout.js | /posts/some-post | [posts, some-post] |
app/posts/layout.js | /posts | [] |
app/posts/layout.js | /posts/some-post | [some-post] |
notFoundNEXT_NOT_FOUND에러를 부르며 현 라우트 segment에 대한 렌더링을 끊는다getServerSideProps, getStaticProps 를 사용하는 다이나믹 라우팅 페이지에서 에러 발생 시 redirect 내부에 notFound: true 를 활요하여 404 를 띄우는 것과 동일한 역할을 한다usage:
import { notFound } from 'next/navigation'
async function fetchUsers(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
const Profile = async({ params }) => {
const user = await fetchUser(params.id)
if (!user) {
notFound()
}
// ...
}
export default Profile
redirectNEXT_REDIRECT에러를 부르며 현 라우트 segment에 대한 렌더링을 끊는다getServerSideProps, getStaticProps 를 사용하는 다이나믹 라우팅 페이지에서 에러 발생 시 redirect 내부에 destination 값을 주어 특정 경로로 리다이렉트 시켜주는 것과 동일한 역할을 한다usage:
import { redirect } from 'next/navigation'
async function fetchTeam(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
const Profile = async({ params }) => {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}