Open16
Next.js 学んだこと
router.refresh()
とは
Next.jsの公式ドキュメント
サーバーに新しいリクエストを行い、データリクエストを再取得し、Server Componentを再レンダリングする。
クライアントは、影響を受けていないクライアント側のReact(useStateなど)やブラウザの状態(スクロール位置など)を失うことなく、更新されたReact Server Componentのペイロードをマージすることができます。
クライアントコンポーネントに影響することなくサーバコンポーネントを再レンダリングしてデータを更新してくれる
pushやreplaceと違い、サーバーからデータをfetchし直すということ。
react-selectを使用時
Warning: Prop `id` did not match. Server: "react-select-2-live-region" Client: "react-select-3-live-region"
のエラーが発生
こちらの記事を参考にしてSelectコンポーネントにinstancedIdを付与することが解決することができた。
JavaScriptのNumber()とparseInt()の違い
Number()に空配列が渡された時に数値の0が返って来る事に要注意です。
parseInt
は、数値を含む文字列のうち、数字部分を取り出し、数値に変換する。
Number
は、数値を含む文字列の意味を解釈し、数値に変換する。文法に合わない文字列の時は、NaNを返却する。
🍰URL の情報を取得する方法について
useRouter・useSearchParams・usePathname・useParams
こちらの記事がまとめてあった
🍰current urlを判定して表示
Auth.jsでrole(admin)を使う方法
prismaで設定するには?
enum Role {
USER
ADMIN
}
model User {
id Int @id @default(autoincrement())
role Role @default(USER)
}
アカウントの永続化にデータベースを使用していない場合
Google アカウントの RefreshToken または AccessToken にアクセスする必要がある
app/api/auth/[...nextauth]/route.ts
app/api/auth/[...nextauth]/route.ts
const options = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
authorization: {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code"
}
}
})
],
}
ミドルウェア
middleware.ts
export { default } from "next-auth/middleware"; // defaultをママ使う。
export const config = {
matcher: ["/((?!register|api|login).*)"], // ?!で否定です。
};
roleがadminの場合だけ許可
import { withAuth } from "next-auth/middleware"
export default withAuth(
function middleware(req) {
console.log(req.nextauth.token)
},
{
callbacks: {
authorized: ({ token }) => token?.role === "admin",
},
}
)
export const config = { matcher: ["/admin"] }
参考
// 認証情報取得
const session = await getCurrentUser();
// ログインしていない場合はログイン画面にリダイレクト
if (!session || session.role !== Role.ADMIN) {
redirect('/login');
}
Google Analytics
アクティブ リンク
usePathname()
'use client';
import { usePathname } from 'next/navigation';
ライブラリを使用してclsxクラス名を切り替える
import clsx from 'clsx';
export default function InvoiceStatus({ status }: { status: string }) {
return (
<span
className={clsx(
'inline-flex items-center rounded-full px-2 py-1 text-sm',
{
'bg-gray-100 text-gray-500': status === 'pending',
'bg-green-500 text-white': status === 'paid',
},
)}
>
// ...
)}