LoginSignup
12
3
新規開発や新技術の検証、導入にまつわる記事を投稿しよう!

Pages RouterからApp Routerへ移行した話 Next.js v13

Last updated at Posted at 2023-06-28

この記事は

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.tsxpage.tsx
    edit.tsxedit/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/routernext/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.tsxpage.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

その他

useSelectedLayoutSegment()

  • ページののpathNameをstringで取得できる

useSelectedLayoutSegments()

  • 階層構造を配列で取得できる → breadcrumbsとかに便利

API

  • ファイル名をroute.tsにすることで、apiとして認識される

最後に

始めにも書きましたが、これは移行の一例です
Next.jsは日に日にアップデートされるので、常に公式ドキュメントを読むことを心がけていきたいところです

最後まで読んでくださりありがとうございました!

12
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3