この記事は
Next.js v13からApp RouterがStableになった事に伴って、PagesからAppへの移行作業をミニマムで行ったので、その備忘録です。
これから移行作業を行うという方は、必ず公式ドキュメントを読んだ上で、一例としてこういう作業があるんだ〜くらいの所感で読んでいただけると幸いです🙇♀️
環境
"next": "13.4.2"
"typescript": "4.9.4"
"@chakra-ui/react": "2.5.5"
基本的な変更
-
ページコンポーネントは、ファイル名を
page.tsx
にする事で認識される
index.tsx
→page.tsx
edit.tsx
→edit/page.tsx
-
client sideのコンポーネントはファイルの一番上に
use client
を記述する
・ファイル内でHooksを使っているなら必須です -
_app.tsxはapp/layout.tsxで
rootのlayout.tsx
ファイルは必須!
Custom Appが使えない →AppPropsは使えず、ReactNodeしかchildrenに渡せない
_app.tsx
const App = ({ Component, pageProps }: AppProps) => {
return (
<ChakraProvider theme={theme}>
<Container>
<Component {...pageProps} />
</Container>
</ChakraProvider>
);
};
layout.tsx
const RootLayout: FC<{ children: ReactNode }> = ({ children }) => {
return (
<html lang="ja">
<body>
<ChakraProvider theme={theme}>{children}</Container>
</body>
</html>
);
};
( <Container>
はrootのpage.tsx
に移動)
layoutの場合、親レイアウトとその子コンポーネントの間でデータを渡すことはできません。ルート内で同じデータを複数回リクエストする場合でも、データを必要とするレイアウト内で直接データを取得することをお勧めします。裏側では、ReactとNext.jsがリクエストをキャッシュし、重複排除することで、同じデータが複数回フェッチされるのを防ぎます。
- もしclientで動くproviderがあるなら、layout.tsxに”use client”をつけてあげるか、別のファイルに”use client”をつけたprovider.tsxを作って切り出してあげて、importしてくる
useRouter
-
import先が
next/router
→next/navigator
useRouterでqueryが取れなくなった
pushで引数に渡せる型がstringだけ -
params:
useParams()
(v13.3から)
const params = useParams();
const id = params?.id;
- query:
useSearchParams()
const searchParams = useSearchParams();
const id = searchParams?.get("id");
- paramsとsearchParamsはPage componentsで取ってこれる
const Page = ({
params,
searchParams
}: {
params: {
eventId: string;
};
searchParams: {
userId: string;
};
}) => {
const eventId = params.eventId;
const userId = searchParams.userId
ただし、searchParams
はpage.tsxでしか使えない
metadata API
-
next/head
は廃止
今まではnext/head
から<Head>
をimportして定義していた
→同じ階層にhead.tsx
かpage.tsx
でmetadataを定義
export const metadata: Metadata = {
title: '...',
description: '...',
}
-
generateMetadata
generateMetadataは引数にparams・searchParamsを持ってこれる(dynamic defind)
ただし、generateMetadataを使えるのはserver component(server side)だけ
type Props = {
params: { id: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata(
{ params, searchParams }: Props,
): Promise<Metadata> {
const id = params.id;
const product = await fetch(`https://.../${id}`).then((res) => res.json());
return {
title: product.title,
};
}
ただし、searchParams
を持てるのは、page.tsx
だけ(layout.tsx
ではparams
のみ使用可能)
Page
Page(Server Components)で検索パラメータにアクセスするには、searchParams プロパティを使用します。Layout
Pageとは異なり、Layout(Server Components)はsearchParamsプロップを受け取りません。これは、共有レイアウトがナビゲーションの間に再レンダリングされないため、ナビゲーションの間にsearchParamsが古くなる可能性があるためです。代わりに、PageのsearchParamsまたはClient ComponentsのuseSearchParams hooksを使用してください。
Chakra ui
-
CacheProvider
を使ってあげる
詳細は公式ドキュメント
その他
useSelectedLayoutSegment()
- ページののpathNameをstringで取得できる
useSelectedLayoutSegments()
- 階層構造を配列で取得できる → breadcrumbsとかに便利
API
- ファイル名をroute.tsにすることで、apiとして認識される
最後に
始めにも書きましたが、これは移行の一例です
Next.jsは日に日にアップデートされるので、常に公式ドキュメントを読むことを心がけていきたいところです
最後まで読んでくださりありがとうございました!