🗂

NextJs チュートリアルをLocal MySqlで

2024/06/09に公開

概要

NextJsのチュートリアルをローカル環境のMysqlに繋げて実装します。
公式チュートリアル

Chapter 1

公式と変わりません。
ターミナルから次のコマンドを実行します。
Windowsの方はGit Bash(コマンドツール)がオススメです。

チュートリアルサンプルコードからnextjs-dashboardというプロジェクトを作成します。

npx create-next-app@latest nextjs-dashboard --use-npm --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example"

処理が完了したら

cd nextjs-dashboard
npm run dev

で起動出来ます。
※VSCodeからターミナルをGitBashで開くとコピペも出来て便利です。

http://localhost:3000から
ブラウザで表示を確認出来ます。
左上側をスクショした画像を載せておきます。

表示確認

Chapter 2

スタイルシートの設定方法を解説しています。

グローバルスタイルの設定

/app/layout.tsx
+ import '@/app/ui/global.css';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  );
}

Tailwind

TailwindはCSSフレームワークです。
クラス名を追加して要素をスタイルします。
例えば、"text-blue-500 "というクラスを追加すると、<h1>のテキストが青くなります

CSS モジュール

CSSモジュールでは、一意のクラス名を自動的に作成することで、
CSSをコンポーネントにスコープすることができます。
つまりcss定義の影響範囲を限定的にして利用する事が出来ます。

Chapter 3

次の2点を解説しています。

  • フォントを追加する設定方法
  • 画像を追加する方法

フォントの追加

fonts.tsを追加します。

/app/ui/fonts.ts
+ import { Inter } from 'next/font/google';

+ export const inter = Inter({ subsets: ['latin'] });

定義したフォントをbodyに適用します。

/app/layout.tsx
import '@/app/ui/global.css';
+ import { inter } from '@/app/ui/fonts';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
-       <body>{children}</body>
+       <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

※antialiasedはTailwindでフォントを滑らかにする設定です。

セカンダリフォントも設定しておきます。
設定しておかないとエラーになります。

/app/ui/fonts.ts
+ import { Inter, Lusitana } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });
 
+ export const lusitana = Lusitana({
+   weight: ['400', '700'],
+   subsets: ['latin'],
+ });

画像の追加

page.tsxに画像を追加します。

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
+ import Image from 'next/image';
 
export default function Page() {
  return (
    // ...
    <div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
      {/* Add Hero Images Here */}
+      <Image
+        src="/hero-desktop.png"
+        width={1000}
+        height={760}
+        className="hidden md:block"
+        alt="Screenshots of the dashboard project showing desktop version"
+      />
    </div>
    //...
  );
}

モバイル用の画像も追加しておきましょう。

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
 
export default function Page() {
  return (
    // ...
    <div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
      {/* Add Hero Images Here */}
      <Image
        src="/hero-desktop.png"
        width={1000}
        height={760}
        className="hidden md:block"
        alt="Screenshots of the dashboard project showing desktop version"
      />
+      <Image
+        src="/hero-mobile.png"
+        width={560}
+        height={620}
+        className="block md:hidden"
+        alt="Screenshot of the dashboard project showing mobile version"
+      />
    </div>
    //...
  );
}

設定したら起動してブラウザで確認してみましょう。
起動コマンドは下記です。

npm run dev

Chapter 4

ダッシュボードページを追加します。
dashboardパスの配下にpage.tsxを追加します。

/app/dashboard/page.tsx
+ export default function Page() {
+   return <p>Dashboard Page</p>;
+ }

dashboardパスの配下にlayout.tsxを追加します。

/app/dashboard/layout.tsx
+ import SideNav from '@/app/ui/dashboard/sidenav';
+  
+ export default function Layout({ children }: { children: React.ReactNode }) {
+   return (
+     <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
+       <div className="w-full flex-none md:w-64">
+         <SideNav />
+       </div>
+       <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
+     </div>
+   );
+ }

ダッシュボードページアクセスするとページを確認出来ます。


http://localhost:3000/dashboard

Chapter 5

<Link>コンポーネント設置

aタグの代わりにLinkタグを使用します。
nav-links.tsxがaタグになっているのでLinkタグに置き換えます。

/app/ui/dashboard/nav-links.tsx
import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
+ import Link from 'next/link';
 
// ...
 
export default function NavLinks() {
  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
-         <a
+         <Link
            key={link.name}
            href={link.href}
            className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
-         </a>
+         </Link>
        );
      })}
    </>
  );
}

アクティブリンクの表示

※公式から抜粋

一般的なUIパターンは、ユーザーが現在どのページにいるのかを示すために、アクティブなリンクを表示することです。これを行うには、URLからユーザーの現在のパスを取得する必要があります。Next.jsはusePathname()というフックを提供しており、これを使用してパスをチェックし、このパターンを実装することができます。

usePathname()はフックなので、nav-links.tsxをクライアントコンポーネントにする必要があります。Reactの "use client "ディレクティブをファイルの先頭に追加し、next/navigationからusePathname()をインポートします。

実装すると画像の用に表示しているページのリンクが青地でハイライトされます。

表示例

clsxライブラリを使うと、リンクがアクティブなときに条件付きでクラス名を適用することができます。

/app/ui/dashboard/nav-links.tsx
+ 'use client';
 
import {
  UserGroupIcon,
  HomeIcon,
  InboxIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
+ import { usePathname } from 'next/navigation';
+ import clsx from 'clsx';

// ...

export default function NavLinks() {
+  const pathname = usePathname();
   return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link
            key={link.name}
            href={link.href}
-           className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
+           className={clsx(
+             'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
+             {
+               'bg-sky-100 text-blue-600': pathname === link.href,
+             },
+           )}
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link>
        );
      })}
    </>
   );
}

Chapter 6

データベースの設定をします。
公式ではVercelにPostgreSQLのデータベースを構築しています。
ここではLocalにMySqlを構築します。

執筆中...

Discussion