Next.jsで実現するオニオンアーキテクチャ (5) - Presentation

:::note warn
記事におけるNext.jsは、v13以降のApp Router （Server Components）を用いる前提での説明となります。
Pages Routerを用いている場合は、適宜Pages Routerでの書き方として読み替えてください。
:::

## この記事は何
最近Next.jsでウェブアプリケーションを作ることが多いのですが、
その時にオニオンアーキテクチャを採用してアプリケーションを作ることが多く、型も固まってきたので数回の記事にわたり紹介をしていきたいと思っています。

前回は

https://qiita.com/getty104/items/968434a5a37f03975735

でInfrastructureについて紹介しました。

今回は`app`ディレクトリ内で実装していくPresentaionについて説明をしていきます。

## Presentationとは
Presentationとは、レイヤーとしては　最も外側に位置し、ユーザーとのインテラクションをとるレイヤーになります。
このレイヤーでは、以下のようなことを行なっていきます。

- UIの描画（処理の出力）
- ユーザーからの入力の受付

これを実現するために、基本的にPresentationではInfrastructureやApplication Serviceへのアクセスを行いながらデータの取得や、ユーザーの入力を元にした処理の実行を行なっていきます。

## Next.jsにおけるPresentationの実行
この章まで色々な処理について紹介してきましたが、ここまでほぼNext.js特有の話はしてきていないと思います。
正直言うと、Presentation以外のレイヤーの処理はNext.js以外の環境でも同じように適用することができます。
Next.jsはこのPresentaionを実装するにあたって必要になってきます。

Next.js v13から、AppRouterという形でServer Componentsを用いることが可能になりました。
このServer Componentsが前項で紹介したようなベージの描画時の処理を実装していく部分になります。
また、v14からはServer Actionsも安定版になったため、ユーザーからの入力を元にした処理はAPIを実装せずともServer Actionsで実装できるようになっています。

Server Components、Server Actionsについては以下をご覧ください。

https://qiita.com/getty104/items/74d975ff02bdf4fa9b2b

https://reffect.co.jp/nextjs/next-js-server-action-14/

## 実装例
今回は例として、以下のようなページを実装してみます。
- URLの`uuid`の値をもとに、そのuuidを持つユーザーが持っている通貨一覧を表示する
- フォームでuuidと通貨の情報を入力すると、送金が行える

```tsx:app/users/[uuid]/page.tsx
import { UserRepository } from '~/infrastructures/UserRepository';
import { UserApplicationService } from '~/applications/UserApplicationService';
import { sendNotification } from '~/utils/sendNotification'
import { Money } from '~/models/users/Money';
import { notFound } from 'next/navigation';

const sendMoney = (formData: FormData): Promise<void> => {
  "use server";

  const sendUserUuid = formData.get("sendUserUuid") as string;
  const receiveUserUuid = formData.get("receiveUserUuid") as string;
  const amount = Number(formData.get("amount") as string);
  const currencyType = formData.get("currencyType") as string;
  const money = new Money({ amount, currencyType });
  const userRepository = new UserRepository();
  const userApplicationService = new UserApplicationService({ userRepository });

  userRepository.sendMoney({
    sendUserUuid,
    receiveUserUuid,
    money,
    sendNotification
  })
}

export const Page = ({ params }: { params: { uuid: string } }) => {
  const userRepository = new UserRepository();
  const userApplicationService = new UserApplicationService({ userRepository });
  const user = userRepository.findByUuid(params.uuid);

  if(!user) return notFound();

  return(
    <div>
      <div>
        {user.getMonies().map((money) => (
          <li key={money.currencyType}>
            {money.amount} {money.currencyType}
          </li>
        ))}
      </div>
      <div>
        <form onSubmit={sendMoney}>
          <input
            type="hidden"
            name="sendUserUuid"
            value={user.uuid}
          />
          <input
            type="text"
            name="receiveUserUuid"
            required
          />
          <input
            type="number"
            name="amount"
            required
          />
          <input
            type="text"
            name="currencyType"
            required
          />
          <button type="submit">送金</button>
        </form>
      </div>
    </div>
  )
}
```

## 最後に
今回はNext.jsを用いたPresentationの実装についての紹介を行いました。
これでNext.jsでのオニオンアーキテクチャの実装の紹介は全てになります。
ここまで読んでいただきありがとうございました。

## 今までの記事

https://qiita.com/getty104/items/afd6a557f90b130269be

https://qiita.com/getty104/items/9b67900d30f9a02c7c7c

https://qiita.com/getty104/items/9ded98cd10d3956c4a9f

https://qiita.com/getty104/items/968434a5a37f03975735