1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsのServer ComponentsとServer Actionsを徹底解説

Posted at

「あれ?どっちを使うべき?」Next.jsのServer ComponentsとServer Actionsを徹底解説

Next.jsのApp Routerで開発していると、「Server Components」と「Server Actions」という言葉をよく目にしませんか?

どちらもサーバーに関連する機能だけど、実際は何が違うの?いつどっちを使えばいいの?

この記事では、この2つの概念の違いを、分かりやすく解説します。

Server Componentsって結局何なの?

Server Componentsは、サーバー上でレンダリングされるReactコンポーネントです。App Routerでは、特に何も指定しなければ、すべてのコンポーネントはデフォルトでServer Componentsになります。

こんなメリットがあります

  • 🔌 データベースに直接アクセスできる: わざわざAPIを経由する必要なし
  • 🔒 APIキーなどの秘密情報を安全に扱える: クライアントに漏れる心配なし

コードで見るとこんな感じ

app/page.tsx(Server Component)
import { getUser } from '@/lib/db';

export default async function UserPage({ params }) {
  // データベースに直接アクセス!クライアントからは見えない!
  const user = await getUser(params.id);
  
  return (
    <div>
      <h1>{user.name}さんのプロフィール</h1>
      <p>メール: {user.email}</p>
    </div>
  );
}

シンプルですね。特別な指示子も必要なく、普通にコンポーネントを書けばOKです。

では、Server Actionsは?

一方、Server Actionsは、クライアントからサーバー上で実行できる非同期関数です。ユーザーがボタンをクリックしたり、フォームを送信したりしたときに、サーバー上で何かの処理をしたい場合に使います。

こんなメリットがあります

  • 📝 フォーム送信が超簡単: わざわざAPIエンドポイントを作る必要なし
  • 🔄 データの更新処理に最適: 作成・更新・削除などの操作がスムーズ
  • 🧩 型安全: TypeScriptとの相性抜群

コードで見るとこんな感じ

app/actions.ts(Server Action)
'use server';  // この魔法の言葉が必要!

import { updateUser } from '@/lib/db';
import { revalidatePath } from 'next/cache';

export async function updateUserAction(formData: FormData) {
  const name = formData.get('name') as string;
  const email = formData.get('email') as string;
  
  // サーバー上でデータベース更新!
  await updateUser({ name, email });
  
  // ページのキャッシュもさっと更新
  revalidatePath('/users');
}
app/edit-profile.tsx
import { updateUserAction } from './actions';

export default function EditProfileForm() {
  return (
    <form action={updateUserAction}>
      <input name="name" type="text" />
      <input name="email" type="email" />
      <button type="submit">更新</button>
    </form>
  );
}

'use server'という指示子がポイントです。これがあることで、この関数はサーバー上で実行されることをNext.jsに伝えています。

一目でわかる違い

項目 Server Components Server Actions
役割 見せるためのもの 変えるためのもの
実行タイミング ページを開いた時 ユーザーが何かしたとき
合言葉 なし(デフォルト) 'use server'
よく使うシーン データ取得 → 表示 フォーム送信、データ更新
呼び出し方 <Component /> action={myAction}

どっちを使うべき?

Server Componentsを選ぶのはこんなとき

  • 👀 データを表示するだけのとき

    • 「ユーザー情報を表示したい」
    • 「商品一覧を見せたい」
  • 💾 データベースから直接データを読み取りたいとき

    • 「DBから最新の投稿を取得して表示したい」

Server Actionsを選ぶのはこんなとき

  • 📝 フォームを送信するとき

    • 「ユーザー登録フォーム」
    • 「お問い合わせフォーム」
  • ✏️ データを変更するとき

    • 「いいねボタンを押したらカウントを増やしたい」
    • 「コメントを投稿したらDBに保存したい」
  • 🔄 ページ内容を更新したいとき

    • 「フィルターを変更したら商品一覧を更新したい」

実際の開発ではこう使い分ける!

「ユーザープロフィール編集ページ」を例に見てみましょう。

app/profile/[id]/page.tsx(Server Component)
import { getUser } from '@/lib/db';
import ProfileForm from './profile-form';

export default async function ProfilePage({ params }) {
  // Server Componentでデータを取得
  const user = await getUser(params.id);
  
  return (
    <div>
      <h1>{user.name}さんのプロフィール</h1>
      {/* 取得したデータをフォームの初期値として渡す */}
      <ProfileForm user={user} />
    </div>
  );
}
app/profile/[id]/actions.ts(Server Action)

'use server';

import { updateUser } from '@/lib/db';
import { revalidatePath } from 'next/cache';

export async function updateProfileAction(userId: string, formData: FormData) {
  const name = formData.get('name') as string;
  const bio = formData.get('bio') as string;
  
  // Server Actionでデータを更新
  await updateUser(userId, { name, bio });
  
  // 更新後はページを再検証
  revalidatePath(`/profile/${userId}`);
}
app/profile/[id]/profile-form.tsx(Client Component)
'use client';

import { updateProfileAction } from './actions';

export default function ProfileForm({ user }) {
  return (
    <form action={formData => updateProfileAction(user.id, formData)}>
      <div>
        <label htmlFor="name">名前</label>
        <input id="name" name="name" defaultValue={user.name} />
      </div>
      <div>
        <label htmlFor="bio">自己紹介</label>
        <textarea id="bio" name="bio" defaultValue={user.bio} />
      </div>
      <button type="submit">更新する</button>
    </form>
  );
}

この例では、

  1. Server Componentでユーザーデータを取得して表示
  2. フォームを通じてServer Actionを呼び出してデータを更新
  3. 更新後にページを再検証して最新の状態を表示

という流れで、それぞれの長所を活かしています。

まとめ

  • 見せることが目的なら → Server Components
  • 変えることが目的なら → Server Actions

両方をうまく組み合わせることで、高速で開発効率の良いアプリケーションが構築できます。Next.jsのApp Routerの真価を発揮するには、この2つを適材適所で使い分けることがポイントです。

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?