Open6

Next.js13での対応記録

nabetsunabetsu

API Routes

https://nextjs.org/docs/pages/building-your-application/routing/api-routes

公式ドキュメントだといかがApp RouterでのAPIの部分

Routing: Route Handlers | Next.js

基本的なルール

route.js|tsファイルがAPIのルートとして認識されるっぽい。
具体例で言うとこんな感じ。

app/api/route.ts/api
app/api/user/route.ts/api/user

Request, Response

Fetch APIのRequest, Responseの他に、それを拡張したNextRequest, NextResponseを使うことができる

こんな感じ

import { NextResponse } from "next/server";

export async function GET(request: Request) {
  return NextResponse.json({ data: "aaaa" });
}

Responseではこんな感じでstatusの設定とかができる。

  if (process.env.OPENAI_API_KEY) {
    const errorMessage = {
      error: {
        message:
          "OpenAI API key not configured, please follow instructions in README.md",
      },
    };
    // https://stackoverflow.com/questions/43997163/how-to-make-request-body-type-compatible-with-requestinit-or-bodyinit-when-using
    return new NextResponse(JSON.stringify(errorMessage), { status: 500 });
  }

PathParameter

pageと同じようにapp/items/[slug]/route.tsのように定義して、同じようにparamsの形でアクセスできる

export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug // 'a', 'b', or 'c'
}

RequestBody

こんな感じでrequest bodyの値を取得できる

import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const res = await request.json();
  return NextResponse.json({ data: res });
}
% curl -X POST -H "Content-Type: application/json" -d '{"name":"太郎", "age":"30"}' localhost:3000/api
{"data":{"name":"太郎","age":"30"}}

参考にした資料

nabetsunabetsu

Layout

_appや_documentのファイルは作らず、レイアウトファイル(app/layout.*)に共通処理を書いていくのが正解っぽい
Providerの設定とかもapp/layout.*に書いていく

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ChakraProvider>
          <AuthProvider>
            <>
              <Hedaer />
              {children}
            </>
          </AuthProvider>
        </ChakraProvider>
      </body>
    </html>
  );
}
nabetsunabetsu

Dynami Route

Path Parameterの取得方法

基本的には以下の通りにすればOK
Routing: Dynamic Routes | Next.js

まずファイルの構成をapp/blog/[slug]/page.jsのようにする。
あとはpropsの中で受け取りたいpath parameterを定義すればOK

export default function Page({ params }: { params: { slug: string } }) {
  return <div>My Post: {params.slug}</div>
}
nabetsunabetsu

Copy機能の実装

ChakraUIではカスタムフックがあるが、単純にinputと1対1の関係で紐づかなかったので独自に実装が必要だった

https://chakra-ui.com/docs/hooks/use-clipboard

クリップボードにコピーする仕組み

以下がわかりやすかったが、Clipboard APIを使う。

navigator.clipboard.writeText(text)

【JavaScript】クリップボードのテキストをコピー・ペーストする【Clipboard API】|Into the Program

コピーボタンの実装

焼き直しにはなっちゃうが、useStateを使ってコピーボタン押下後3秒間は表示内容を変更。
ボタンクリック時に呼ばれるonCopyでフォームの内容をいい感じにまとめてクリップボードにコピー

  const [hasCopied, setHasCopied] = useState(false);
  ...
  const onCopy = () => {
    setHasCopied(true);
    const text = "inputを適用にここに整形して渡す";
    navigator.clipboard.writeText(text);
    setTimeout(() => {
      setHasCopied(false);
    }, 3000);
  };
  ...
        <Button
          onClick={onCopy}
        >
          {hasCopied ? "Copied!" : "Copy"}
        </Button>