Next.jsとReact入門:基本から実践まで
はじめに
フロントエンド開発の世界は日々進化しており、多くの用語や技術が存在するため、初心者にとっては混乱することもあるでしょう。この記事では、React、Next.jsの基本的な概念から始め、実際のプロジェクトの作り方、そして便利なライブラリとその使い方までを解説します。
1. 基本知識
Reactって何?初心者にもわかるように説明すると
Reactは「JavaScriptライブラリ」です。これはつまり、誰かが書いた便利なコードの集まりで、私たちがゼロから全部書く必要がないようにしてくれるものです。
Reactは特に「ユーザーインターフェイス(UI)」、つまりユーザーが見て操作する画面を作るのに特化しています。
簡単に例えると:
- 従来の方法: 毎回新しい紙(HTML)に全部書き直して見せる
- Reactの方法: 紙の必要な部分だけを書き換えて見せる
Reactの基本的な特徴をとてもシンプルに説明すると:
-
ブロック遊びのような開発(コンポーネント):
- 例えば「ボタン」「ヘッダー」「カード」などの部品を一度作っておけば、何度でも再利用できます。
- レゴブロックのように、小さな部品を組み合わせて大きなものを作ります。
-
裏技で速くなる仕組み(仮想DOM):
- 画面に変更があったとき、全部を描き直すのではなく、変わった部分だけを更新します。
- 例えるなら、家の一部屋だけリフォームするのと、家全体を建て直すのとの違いです。
-
一方通行のデータの流れ(単方向データフロー):
- データは常に「親→子」の一方向に流れます。
- これにより「今どのデータがどこにあるのか」が分かりやすくなります。
- 例えるなら、川の上流から下流へと水が流れるようなイメージです。
-
HTMLとJavaScriptの融合(JSX):
- HTMLとJavaScriptを一緒に書けるようにした特別な書き方です。
- 例えば:
function あいさつ() { const 名前 = "たろう"; return <h1>こんにちは、{名前}さん!</h1>; }
- 中括弧
{}
の中にJavaScriptの変数や計算を入れられます。
Next.jsって何?何が「Next(次)」なの?
Next.jsは「Reactフレームワーク」です。Reactを使いやすくするための道具セットと考えてください。
例えるなら:
- Reactは「料理の基本技術」
- Next.jsは「調理器具と調味料がセットになったキッチンセット」
Next.jsが特に便利な理由(とても簡単に説明):
-
ページの読み込みがとても速い:
- サーバー側で事前にページを準備してくれる(サーバーサイドレンダリング:SSR)
- 一度アクセスがあったページは完成品としてキャッシュしておける(静的サイト生成:SSG)
-
ページの管理が簡単:
- ファイルを作るだけで自動的にURLが設定される
- 例:
pages/about.js
というファイルを作ると、/about
というURLになる
-
APIも簡単に作れる:
- データを取得・保存するための仕組みを簡単に作れる
- 例:
pages/api/hello.js
というファイルを作ると、/api/hello
というAPIエンドポイントになる
-
便利な機能が最初から使える:
- 画像の最適化
- CSSの取り込み
- ルーティング(ページ間の移動)
よく聞く用語を「例え話」で理解しよう
-
コンポーネント: レゴブロックのようなパーツ。「ボタン」「カード」「ヘッダー」など。
-
プロップス (Props): 親から子へのプレゼント。
// 親コンポーネント <ボタン 色="赤" テキスト="クリックしてね" /> // 子コンポーネント(ボタン)が親からの情報を受け取る function ボタン(props) { return <button style={{color: props.色}}>{props.テキスト}</button>; }
-
ステート (State): コンポーネントの「記憶」や「状態」。
function カウンター() { // [現在の値, 更新する関数] = useState(初期値); const [カウント, カウント更新] = useState(0); return ( <div> <p>現在の数: {カウント}</p> <button onClick={() => カウント更新(カウント + 1)}> 増やす </button> </div> ); }
-
フック (Hooks): 便利な魔法の道具。useState(状態を管理)、useEffect(副作用を処理)など。
-
レンダリング: 画面に表示すること。レストランでの料理の提供に例えられます。
-
ハイドレーション: 「乾いた」HTMLに「水分(JavaScript)」を与えて「活性化」させること。
- サーバーが送る静的なHTMLに、ブラウザでJavaScriptを組み合わせて動きを付ける過程です。
Reactとは何か?
Reactは、Facebookが開発したJavaScriptライブラリで、ユーザーインターフェイスを構築するために使用されます。以下がReactの主要な特徴です:
- コンポーネントベース: UIをコンポーネントと呼ばれる独立した再利用可能な部品に分割します。
- 仮想DOM: 実際のDOMの軽量なコピーを作成し、変更があった部分のみを更新することでパフォーマンスを向上させます。
- 単方向データフロー: データは親から子へと一方向に流れ、予測可能なコードとなります。
- JSX: JavaScriptの中にHTMLのような構文を書くことができる拡張構文です。
Next.jsとは何か?
Next.jsはReactのフレームワークで、以下のような機能を提供します:
- サーバーサイドレンダリング (SSR): 初回読み込みを高速化し、SEOを向上させます。
- 静的サイト生成 (SSG): ビルド時にHTMLを生成し、高速なページ読み込みを実現します。
- ファイルベースのルーティング: ファイル構造に基づいて自動的にルートが生成されます。
- APIルート: サーバーレス関数としてAPIエンドポイントを作成できます。
- ビルトインCSS/Sassサポート: スタイルを簡単に追加できます。
重要な用語集
- コンポーネント: UIの独立した部分。
- プロップス (Props): 親コンポーネントから子コンポーネントへデータを渡す手段。
- ステート (State): コンポーネント内で管理されるデータ。
- フック (Hooks): 関数コンポーネントでステートやライフサイクル機能を使うための関数。
- レンダリング: コンポーネントをブラウザ上に表示するプロセス。
- ハイドレーション: サーバーでレンダリングされたHTMLにクライアント側のJavaScriptの機能を追加すること。
2. 環境設定
必要なツール
- Node.js: JavaScriptのランタイム環境。
- npm または yarn: パッケージマネージャー。
- コードエディタ: Visual Studio Code(推奨)。
- Git: バージョン管理システム。
Node.jsとnpmのインストール
- Node.js公式サイトからインストーラーをダウンロード。
- インストーラーを実行し、指示に従う。
- インストール後、ターミナルで以下のコマンドを実行して確認:
node -v
npm -v
3. プロジェクトの作成方法
Next.jsプロジェクトの作成
以下のコマンドを実行してNext.jsプロジェクトを作成します:
npx create-next-app@latest my-next-app
# または
yarn create next-app my-next-app
プロジェクト作成時に表示される質問に答えてください:
- TypeScriptを使用するか?
- ESLintを使用するか?
- Tailwind CSSを使用するか?
-
src/
ディレクトリを使用するか? - Appルーターを使用するか?
- カスタマイズをするか?
プロジェクトの構造
Next.jsの基本的なプロジェクト構造:
my-next-app/
├── .next/ # ビルドされたファイル(自動生成)
├── node_modules/ # インストールされたパッケージ
├── public/ # 静的ファイル(画像、フォントなど)
├── src/ # ソースコード(オプション)
│ ├── app/ # Appルーター(新しい方式)
│ │ └── page.js # ルートページ
│ ├── pages/ # Pagesルーター(従来の方式)
│ │ ├── _app.js # アプリ全体のレイアウト
│ │ ├── _document.js # HTMLドキュメント構造
│ │ ├── index.js # ホームページ
│ │ └── api/ # APIルート
│ ├── components/ # 再利用可能なコンポーネント
│ └── styles/ # CSSファイル
├── .eslintrc.json # ESLint設定
├── next.config.js # Next.js設定
├── package.json # プロジェクト依存関係
└── tsconfig.json # TypeScript設定(使用する場合)
開発サーバーの起動
cd my-next-app
npm run dev
# または
yarn dev
これでhttp://localhost:3000
でアプリケーションが起動します。
4. Reactの基本
コンポーネントの作成
// components/Button.js
export default function Button({ text, onClick }) {
return (
<button onClick={onClick} className="my-button">
{text}
</button>
);
}
フックの使用
// pages/counter.js
import { useState } from 'react';
import Button from '../components/Button';
export default function Counter() {
// ステートの初期化
const [count, setCount] = useState(0);
// カウントを増やす関数
const increment = () => {
setCount(count + 1);
};
return (
<div>
<h1>カウンター: {count}</h1>
<Button text="増やす" onClick={increment} />
</div>
);
}
useEffectの使用
import { useState, useEffect } from 'react';
export default function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// コンポーネントがマウントされたときに実行
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
// クリーンアップ関数(コンポーネントがアンマウントされたときに実行)
return () => clearInterval(interval);
}, []); // 空の依存配列は、このエフェクトがマウント時に一度だけ実行されることを意味する
return <div>経過時間: {seconds}秒</div>;
}
5. Next.jsの基本機能
ページとルーティング
Next.jsではフォルダ構造がそのままURLパスになります。
Appルーター(新しい方式):
src/app/about/page.js → /about
src/app/blog/[slug]/page.js → /blog/:slug
Pagesルーター(従来の方式):
src/pages/about.js → /about
src/pages/blog/[slug].js → /blog/:slug
レイアウト
Appルーター:
// src/app/layout.js
export default function RootLayout({ children }) {
return (
<html lang="ja">
<body>
<header>ヘッダー</header>
<main>{children}</main>
<footer>フッター</footer>
</body>
</html>
);
}
Pagesルーター:
// src/pages/_app.js
import '../styles/globals.css';
export default function MyApp({ Component, pageProps }) {
return (
<>
<header>ヘッダー</header>
<Component {...pageProps} />
<footer>フッター</footer>
</>
);
}
データフェッチング
サーバーサイドレンダリング (SSR):
// pages/ssr-page.js
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return {
props: { data }, // ページコンポーネントへpropsとして渡される
};
}
export default function SSRPage({ data }) {
return <div>{data.title}</div>;
}
静的サイト生成 (SSG):
// pages/ssg-page.js
export async function getStaticProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return {
props: { data },
revalidate: 60, // 60秒ごとに再生成(ISR)
};
}
export default function SSGPage({ data }) {
return <div>{data.title}</div>;
}
APIルート
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello World' });
}
6. スタイリング
CSSモジュール
/* styles/Button.module.css */
.button {
background-color: blue;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
}
// components/StyledButton.js
import styles from '../styles/Button.module.css';
export default function StyledButton({ text }) {
return <button className={styles.button}>{text}</button>;
}
Tailwind CSS
Next.jsプロジェクトにTailwind CSSを追加:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.jsを設定:
// tailwind.config.js
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx}',
'./src/components/**/*.{js,ts,jsx,tsx}',
'./src/app/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};
グローバルCSSファイルに以下を追加:
/* styles/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
使用例:
export default function TailwindButton({ text }) {
return (
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
{text}
</button>
);
}
7. 便利なライブラリとその導入方法
状態管理
Redux Toolkit
インストール:
npm install @reduxjs/toolkit react-redux
使用例:
// store/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
// store/index.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
// pages/_app.js
import { Provider } from 'react-redux';
import { store } from '../store';
export default function MyApp({ Component, pageProps }) {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
Zustand
より軽量な状態管理ライブラリ:
npm install zustand
使用例:
// store/useStore.js
import create from 'zustand';
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
export default useStore;
// pages/zustand-counter.js
import useStore from '../store/useStore';
export default function ZustandCounter() {
const { count, increment, decrement } = useStore();
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
フォーム管理
React Hook Form
インストール:
npm install react-hook-form
使用例:
import { useForm } from 'react-hook-form';
export default function ContactForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log(data);
// フォームデータの処理
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>名前</label>
<input {...register('name', { required: '名前は必須です' })} />
{errors.name && <p>{errors.name.message}</p>}
</div>
<div>
<label>メール</label>
<input
{...register('email', {
required: 'メールは必須です',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: '有効なメールアドレスを入力してください',
},
})}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<button type="submit">送信</button>
</form>
);
}
UIコンポーネントライブラリ
Chakra UI
インストール:
npm install @chakra-ui/react @emotion/react @emotion/styled framer-motion
設定:
// pages/_app.js
import { ChakraProvider } from '@chakra-ui/react';
export default function MyApp({ Component, pageProps }) {
return (
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
);
}
使用例:
import { Button, Box, Heading } from '@chakra-ui/react';
export default function ChakraExample() {
return (
<Box p={5}>
<Heading mb={4}>Chakra UI Example</Heading>
<Button colorScheme="blue">ボタン</Button>
</Box>
);
}
Material UI
インストール:
npm install @mui/material @emotion/react @emotion/styled
使用例:
import { Button, Box, Typography } from '@mui/material';
export default function MUIExample() {
return (
<Box sx={{ p: 5 }}>
<Typography variant="h4" gutterBottom>
Material UI Example
</Typography>
<Button variant="contained" color="primary">
ボタン
</Button>
</Box>
);
}
データフェッチング
SWR
インストール:
npm install swr
使用例:
import useSWR from 'swr';
// フェッチャー関数
const fetcher = (...args) => fetch(...args).then(res => res.json());
export default function UserProfile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher);
if (error) return <div>エラーが発生しました</div>;
if (isLoading) return <div>読み込み中...</div>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
}
React Query
インストール:
npm install @tanstack/react-query
設定:
// pages/_app.js
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
export default function MyApp({ Component, pageProps }) {
return (
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
);
}
使用例:
import { useQuery } from '@tanstack/react-query';
export default function ReactQueryExample() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(res => res.json()),
});
if (isLoading) return <div>読み込み中...</div>;
if (error) return <div>エラー: {error.message}</div>;
return (
<div>
<h1>ユーザー一覧</h1>
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
8. TypeScriptの導入
TypeScriptを使用するとコード品質が向上します。
新規プロジェクトでTypeScriptを使用する場合:
npx create-next-app@latest my-ts-app --typescript
既存のプロジェクトにTypeScriptを追加する場合:
npm install --save-dev typescript @types/react @types/node
.js
ファイルを.tsx
(Reactコンポーネント用)または.ts
(普通のTypeScriptファイル用)に変換します。
例:
// components/Button.tsx
interface ButtonProps {
text: string;
onClick?: () => void;
variant?: 'primary' | 'secondary';
}
export default function Button({ text, onClick, variant = 'primary' }: ButtonProps) {
return (
<button
onClick={onClick}
className={`button ${variant === 'primary' ? 'primary' : 'secondary'}`}
>
{text}
</button>
);
}
9. プロジェクトのデプロイ
Vercelへのデプロイ
VercelはNext.jsの開発元であり、最も簡単にデプロイできるプラットフォームです。
- Vercelにアカウントを作成
- GitHubリポジトリと連携
- リポジトリをインポート
- 必要な環境変数を設定
- デプロイボタンをクリック
Netlifyへのデプロイ
Netlifyも人気のあるホスティングサービスです。
- Netlifyにアカウントを作成
- 「New site from Git」を選択
- GitHubリポジトリを選択
- ビルド設定:
- Build command:
npm run build
- Publish directory:
.next
- Build command:
- 「Deploy site」をクリック
10. まとめと次のステップ
この記事では、React、Next.jsの基本から、実際のプロジェクト作成、そして便利なライブラリの導入までを解説しました。フロントエンド開発の世界は広く、常に進化していますが、この記事を通じて基本的な理解が得られたことを願っています。
次のステップとしては:
- 小さなプロジェクトを作成して経験を積む
- React、Next.jsの公式ドキュメントを読む
- オープンソースプロジェクトに貢献する
- コミュニティに参加してアイデアや経験を共有する
何か質問や疑問があれば、コメント欄で気軽に質問してください。皆さんのフロントエンド開発の旅が実り多きものになりますように!