Next.jsをゼロからマスターする Part 5

前置き
今回の「Next.jsをゼロからマスターする」は、少し難しいです。なので、初めて触れる方は、気楽に読んでください。繰り返しNext.jsでプロジェクトに触れていると、自然と使えるようになる知識です。初見では、わからないのが普通です。最初は苦しく感じるかもしれませんが、何回も繰り返してコードを実行すると、なんとなくわかってくると思います。
Next.jsのプロジェクト作成
Next.jsのプロジェクト作成の手順を説明します。
- コマンドラインツール(ターミナルやコマンドプロンプト)を開きます。
- プロジェクトを作成したいディレクトリに移動します。
- 以下のコマンドを実行して、新しいNext.jsプロジェクトを作成します。
npx create-next-app@latest my-shadcnui-app
ここで、”my-shadcnui-app”はあなたのプロジェクト名です。好きな名前に変更できます。
- プロジェクト作成中に表示される設定オプションに答えます。TypeScriptを使用するかどうかなど、いくつかの質問があります。
注意: Next.jsのバージョン14.2.15を使用して、プロジェクトを作成した場合の事例です。バージョンが異なると、これらのステップが異なる場合があります。
ステップ | 回答例 (デフォルト) |
---|---|
Need to install the following packages: create-next-app@14.2.15 Ok to proceed? (y) | Returnボタン |
?Would you like to use TypeScript?› No / Yes | Yesを選択 |
?Would you like to use ESLint?› No / Yes | Yesを選択 |
? Would you like to use Tailwind CSS? › No / Yes | Yesを選択 |
?Would you like to use src/directory?› No / Yes | Yesを選択 ←前回(バージョン14.2.12)からデフォルトがYesに変更 |
?Would you like to use App Router? (recommended)› No / Yes | Yesを選択 |
?Would you like to customize the default import alias (@/*)?› No / Yes | Noを選択 |

Next.jsプロジェクトが作成できたらVSCodeを開きFile ⇨ Open Folderから「my-shadcnui-app」を開きます。

Next.js 14のsrc(source)フォルダを使用したプロジェクト構成の基本的なツリー図を以下に示します。
my-project/
├── src/ <— src(source)フォルダが作成された
│ ├── app/ <— src(source)フォルダの下に、app/フォルダが作成された
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ ├── lib/
│ └── styles/
├── public/
├── package.json
├── tsconfig.json <— tsconfig.jsonは、Typescript言語に関する設定が書かれたファイル
└── next.config.js
この構成について解説します。
- src/: ソースコードのルートディレクトリ。アプリケーションのメインコードはここに配置されます。
- src/app/: App Routerのルートディレクトリ。ページやレイアウトファイルが含まれます。
- src/components/: 再利用可能なReactコンポーネントを格納するディレクトリ。
- src/lib/: ユーティリティ関数や共通ロジックを格納するディレクトリ。
- src/styles/: グローバルスタイルやCSSモジュールを格納するディレクトリ。
- public/: 静的ファイル(画像、フォントなど)を格納するディレクトリ。
補足: src (source)フォルダを使っても、App Routerのページは、app/フォルダ以下のpage.tsxが表示される
@/の定義について
@/は通常、tsconfig.jsonファイルで定義されます。
このファイルはプロジェクトのルートディレクトリに配置されています。
tsconfig.jsonの中で、以下のように設定されていることが多いです。
{
”compilerOptions”: {
”baseUrl”: “.”,
”paths”: {
”@/“: [“./src/“]
}
}
}
この設定により、@/はsrc/ディレクトリを指すようになります。例えば、@/components/Button は /src/components/Button を参照することになります。
この設定によって、プロジェクト内での相対パスの使用が簡略化され、コードの可読性と保守性が向上します。

TSXにおける@の使用例
TSXファイルで@を使用する主な目的は、インポートパスを簡略化することです。
以下に具体的な例を示します。
import { Button } from “@/components/ui/button”;
import { useUser } from “@/lib/hooks/useUser”;
import { formatDate } from “@/utils/dateFormatter”;
export default function UserProfile( ) {
const { user } = useUser( );
return (
<div>
<h1>{user.name}</h1>
<p>Joined on: {formatDate(user.joinDate)}</p>
<Button>Edit Profile</Button>
</div>
);
}
この例では、@が以下のように使用されています。
- @/components/ui/button: UIコンポーネントのインポート
- @/lib/hooks/useUser: カスタムフックのインポート
- @/utils/dateFormatter: ユーティリティ関数のインポート
@を使用することで、プロジェクトのルートディレクトリ(通常はsrc/)からの相対パスを簡潔に表現できます。これにより、以下のメリットがあります。
- コードの可読性向上: 長い相対パスを短縮できます。
- メンテナンス性の向上: ファイルの移動時にインポートパスの修正が容易になります。
- 一貫性の確保: プロジェクト全体で統一されたインポート方法を使用できます。
この@の使用方法は、前述のtsconfig.jsonの設定によって可能になります。適切に設定することで、TypeScriptコンパイラとエディタの両方が@を正しく解釈し、コード補完やナビゲーションをサポートします。
ここだけ覚えたらOK
- src (source)フォルダを使っても、App Routerのページは、app/フォルダをパスのルートと、パスとフォルダが対応したpage.tsxが表示される
- import文で@を使った書き方ができる
Next.jsのコンポーネントの再利用性
Next.jsでは、Reactのコンポーネントベースの設計思想を活用しています。
これは、UIの各部分を独立した「部品」(コンポーネント)として作成し、それらを組み合わせて複雑なインターフェースを構築する方法です。
例えば
- 「ボタン」コンポーネントを作成し、それを「フォーム」、「ナビゲーション」、「モーダル」など、様々な場所で再利用できます。
- 「ヘッダー」コンポーネントを一度作成すれば、全てのページで簡単に使い回せます。
この方法には以下のメリットがあります。
- コードの重複を減らし、保守性が向上します。
- 一貫したデザインを簡単に維持できます。
- 大規模なアプリケーションでも、管理しやすい構造を保てます。
つまり、Next.jsのコンポーネントは、再利用可能なLEGOブロックのようなものだと考えられます。必要な「部品」を組み合わせて、効率的にWebアプリケーションを構築できるのです。
Reactコンポーネントと、別のReactコンポーネントでデータを受け渡す: props
propsは、propertiesの略語です。(英語でproperiesは、「所有物」の意味です)
Reactのpropsは、コンポーネント間でデータを受け渡すための仕組みです。
- データを渡すために使用されます。
- propsは、変数の位置に定義します。
- 読み取り専用であり、子コンポーネント内で直接変更することはできません。
- オブジェクト、配列、関数など、あらゆる型のデータを渡すことができます。
- コンポーネントの再利用性と柔軟性を高めます。
propsの使い方
子コンポーネント(部品)を、親コンポーネント(ページ)に表示させてみます。
その際、親コンポーネントで定義したデータを、子コンポーネントに渡して表示します。
ファイル構成です。
my-nextjs-project/
├── node_modules/
├── public/
│ └── favicon.ico
├── src/
│ ├── app/
│ │ ├── layout.tsx
│ │ └── page.tsx <—- 親コンポーネントで、子供コンポーネントを表示させる。データは、親から子へ渡す。
│ └── components/
│ └── child-component.tsx <—- 子供コンポーネントを作る
├── .gitignore
├── next.config.js
├── package.json
├── README.md
└── tsconfig.json
まず、srcフォルダー内に componentsフォルダーを作成します。その中に child-component.tsx というファイルを新しく作成します。そして、child-component.tsxの中に以下のコードを書いていきます。
/src/components/child-component.tsx
// 子供コンポーネント
interface ChildComponentProps { // <— propsの型をつくる
firstName: string;
lastName: string;
}
const ChildComponent = (props: ChildComponentProps) => { // <— 親コンポーネントからデータを受け取る変数。
return (
<div> <div className=”bg-blue-400″>First Name: {props.firstName}</div>
<div className=”bg-red-400″>Last Name: {props.lastName}</div> </div>
)
};
export default ChildComponent

次に、page.tsxに以下のコードを書いていきます。
/src/app/page.tsx
// 親コンポーネント
import ChildComponent from “@/components/child-component”;
export default function Home( ) { return (
<div>
<ChildComponent firstName=”Taro” lastName=”Yamada” />
</div>
);
}
上記のコードが書けたら保存をし、VSCodeのターミナルを立ち上げ「npm run dev」を入力してNext.jsにアクセスします。


このコードは、React(Next.js)でpropsを使用して親コンポーネントから子コンポーネントにデータを渡す例を示しています。以下に解説します。
- 子コンポーネント(ChildComponent)
-
- src/components/child-component.tsxに定義されています。
- propsとしてfirstNameとlastNameを受け取ります。
- 受け取ったpropsを使って、名前を表示します。
- 親コンポーネント(Home)
-
- src/app/page.tsxに定義されています。
- ChildComponentをインポートして使用します。
- ChildComponentにfirstName=”Taro”とlastName=”Yamada”というpropsを渡しています。
このように、親コンポーネントで定義したデータ(この場合は”Taro”と”Yamada”)を子コンポーネントに渡し、子コンポーネントでそのデータを使用して表示を行っています。これがReactにおけるpropsの基本的な使い方です。
また、@/components/child-componentというインポート文は、前述のtsconfig.jsonの設定により、src/components/child-component.tsxを指しています。
部品としてButtonを作って、ページに表示させてみる

以下は、Next.jsでTailwind CSSを使用してデザインしたボタンのTSXコードの例です。
まず、Componentsフォルダーに、新しくmybutton.tsxファイルを作成します。
mybuttonFileに、以下のコードを書いていきます。
/src/components/mybutton.tsx
// 子供コンポーネント
interface MyButtonProps {
onClick: ( ) => void;
children: React.ReactNode;
}
const MyButton = ({ onClick, children }: MyButtonProps) => {
return (
<button
onClick={onClick}
className=”bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline transition duration-300 ease-in-out”
>
{children}
</button>
);
};
export default MyButton;

このコードでは、以下のTailwind CSSクラスを使用しています。
- bg-blue-500: 青色の背景
- hover:bg-blue-700: ホバー時に濃い青色に変更
- text-white: 白色のテキスト
- font-bold: 太字のフォント
- py-2 px-4: パディング(上下2、左右4)
- rounded: 角丸
- focus:outline-none focus:shadow-outline: マウスのフォーカスがボタンにあたった時のスタイル
- transition duration-300 ease-in-out: スムーズな遷移効果
このボタンコンポーネントは、クリックイベントと子要素を受け取り、ボタンを表示します。
次に、以下のコードをpage.tsxに書いていきます。
/src/app/page.tsx
// 親コンポーネント
“use client”
import MyButton from “@/components/mybutton”;
export default function Home( ) {
const handleClick = ( ) => {
alert(“Hello World!”);
}
return (
<div className=”bg-green-300 min-h-screen w-full flex items-center justify-center”>
<MyButton onClick={handleClick}>My Button</MyButton>
</div>
)
}
上記のコードを書いたら保存をし、VSCodeのターミナルを立ち上げ「npm run dev」を入力しNext.jsにアクセスします。


Next.jsのApp Routerを使用したページコンポーネントの例です。以下に解説します。
- 1. ‘use client’ ディレクティブ
-
このディレクティブは、このコンポーネントがクライアントサイドでレンダリングされることを示します。これにより、ブラウザ側で実行される動的な機能(この場合はonClickイベント)を使用できます。
- 2. コンポーネントのインポート
-
import Button from “@/components/mybutton”; この行で、先ほど作成したカスタムButtonコンポーネントをインポートしています。
- 3. Home コンポーネント
-
これはページのメインコンポーネントです。App Routerでは、page.tsxファイル内のデフォルトエクスポートがそのルートのページコンポーネントになります。
- 4. handleClick 関数
-
ボタンがクリックされたときに実行される関数です。この例では、単純に “Hello World!” というアラートを表示します。
- 5. レンダリング
-
Homeコンポーネントは、<Button>コンポーネントをレンダリングします。
このButtonには以下のpropsが渡されています。- onClick={handleClick}: クリックイベントのハンドラーを指定
- My button: ボタンのテキストコンテンツ(子要素)として指定
このコードにより、ページにカスタムデザインのボタンが表示され、クリックするとアラートが表示されるようになります。これは、コンポーネントの再利用性とイベント処理の基本的な例を示しています。
use client 宣言 (ディレクティブ)について
Next.js 14のレンダリングについて、説明します。この図は、’use client’と’use server’ディレクティブの役割と、サーバーコンポーネントとクライアントコンポーネントの関係を示しています。

この図は以下の要点を示しています。
- Next.jsアプリケーションは、サーバーコンポーネントとクライアントコンポーネントの両方を含むことができます。
- サーバーコンポーネントはサーバーサイドでレンダリングされ、初期HTMLを生成します。
- ‘use client’ディレクティブを使用したコンポーネントは、クライアントサイドでレンダリングされ、インタラクティブな機能を提供します。
- ‘use server’ディレクティブを使用したサーバーアクションは、サーバーサイドで処理され、必要に応じてコンポーネントを再検証します。