Amplify Gen2のform generateを試してみた

2024.04.10

NTT東日本の中村です。

昨年発表されたAmplify Gen2(プレビュー)ですが、日々機能が少しづつ追加されており、完成度が高まってきました。 前回の記事で作成したNextJSのWebアプリケーションを使い、form generate(フォームの生成機能)を試してみました。

Amplify Gen2のform generateの概要

定義されたデータモデルを元に、データ作成・データ更新の機能を生成する機能です。

データモデルが定義されると、例えば管理画面を設けて、そのデータベースへCRUD(Create、Read、Update、Delete)操作を行いたいようなケースが存在します。通常はその画面の設計・開発が必要になりますが、フォームの生成機能により、画面設計のコードが自動生成され、開発の手間を減らすことができます。 俗にScaffoldと呼ばれる機能で、pythonで言うDjangoや、PHPではCakePHPなどでも使える機能です。

Amplify Gen2のgenerate formはCRUDの中から、Create、UpdateのReactコンポーネントを提供しているようです。

個人的に、Amplify Gen2の目玉機能は、SandBoxによる開発者個別のAWSリソースを生成できることと、このform generateになるのではないかと感じています。 まだドキュメントに詳しい内容が無く、実際に挙動を確認してみました。

フォームを生成してみた

コマンドもシンプルです。
Stack、もしくはAmplify ProjectのBranchを指定すると、コードを生成してくれます。
モデルの絞り込み、出力先ディレクトリの設定が出来るくらいで、後はおまけです。

amplify generate forms

Generates UI forms

Stack identifier
  --stack  A stack name that contains an Amplify backend                [string]

Project identifier
  --app-id  The Amplify App ID of the project                           [string]
  --branch  A git branch of the Amplify project                         [string]

Form Generation
  --out-dir  A path to directory where generated forms are written.
  --models   Model name to generate                                      [array]

Options:
  --debug    Print debug logs to the console          [boolean] [default: false]
  --help     Show help                                                 [boolean]
  --profile  An AWS profile name.                                       [string]

前回作成したDataのモデルで作成します。

チュートリアルがベースですが、PKがtag、SKがcreateDateの複合キーに変更しているので
複合キーでの作成・更新に対応できるかどうかがポイントになります。

amplify/data/resource.ts

const schema = a.schema({
  Todo: a
    .model({
      tag: a.string().required(),
      content: a.string(),
      done: a.boolean(),
      createDate: a.string().required(),
      priority: a.enum(["low", "medium", "high"]),
    })
    .identifier(["tag", "createDate"])   //複合キーにカスタムしている
    .authorization([a.allow.owner()]),

生成

では、フォームを生成していきます。
今回は事前にSandBoxを作成し、sandBoxのcloudFormationStackをパラメータに指定します。

npx amplify generate forms --stack amplify-nextamplifygen2-nakamura-sandbox-6943a9e2ce

プロジェクトルートのui-componentsフォルダに、Create,Updateのコンポーネントが生成されました。
型定義ファイルはありますが、jsxで出力されていますね。
graphqlフォルダはgraphqlクエリがあります。今回使わないqueriesとsubscriptionsも格納されています。

create

何も考えず、作成されたコンポーネントを組み込んでみました。

app/create/page.tsx

 import TodoCreateForm from "@/ui-components/TodoCreateForm";
 
 export default function CreatePage() {
   return (
     <div style={{ backgroundColor: "white" }}>
       <TodoCreateForm />
     </div>
   );
 }

表示されました。項目を入力して、登録してみます。

あっさりとデータが追加され、表示されました。

update

生成されたコンポーネントのロジックを確認してみました。
更新は、更新対象となるレコードのキーか、レコードの値を直接渡す必要があります。

ui-components/TodoUpdateForm.jsx

   React.useEffect(() => {
     const queryData = async () => {
       const record = idProp
         ? (
             await client.graphql({
               query: getTodo.replaceAll("__typename", ""),
               variables: { ...idProp },
             })
           )?.data?.getTodo
         : todoModelProp;
       setTodoRecord(record);
     };
     queryData();
   }, [idProp, todoModelProp]);

PKがtag、SKがcreateDateの複合キーになっているので、コンポーネントに複合キーの値を渡す必要があります。 リスト表示部分に更新ボタンを追加しました。

app/page.tsx

       <ul>
         {rangeTodoList!.map((rangeTodo) => (
           <li key={rangeTodo!.tag + rangeTodo!.createDate}>
             {rangeTodo!.createDate}&nbsp;:&nbsp;{rangeTodo!.content}
             <Link
               style={{
                 border: "1px solid tomato",
               }}
               href={`/update?tag=${rangeTodo!.tag}&createDate=${
                 rangeTodo!.createDate
               }`}
             >
               更新
             </Link>
           </li>
         ))}
       </ul>

更新対象のボタンを押すと、更新画面に遷移します。

対象のレコードが表示されています。 項目を書き換えて、送信を押します。

一覧画面に戻ると、項目が更新されていました。

まとめ

Amplify Gen2のform generateを使用すると、データの作成、更新を行うフォームが簡単に生成できます。

CRUD機能のような「毎回作らなければいけない機能」の工数を減らして、本来実装するべきビジネスロジックに集中できるというのは、Amplifyの変わらないメリットだと思います。