はじめに
前回まではReact Hook FormとZodという入力フォームに必要な機能を揃えたライブラリを活用して「入力フォーム」を作り、「アカウント作成する」ボタンを押すと、入力内容がコンソールログで確認できるというところまで実装しました。
今回は入力内容をサーバーアクションに渡す処理を実装していきます。最終的にはデータベースに登録していくのですが、処理が複雑なため2回に記事を分けて解説していきます。
今回のゴール
この記事のゴールはアカウント登録画面で名前、メールアドレス、パスワードを入力。
その後、サーバーアクションで入力内容を確認し、エラーが発生した場合は、入力画面にエラー通知を返す処理を実装します。
サーバーアクションの作成
まずは新しくactions
フォルダを作成し、register.ts
ファイルを作成します。
'use server'
import { z } from 'zod'
import { RegisterSchema } from '@/schema'
export const register = async (values: z.infer<typeof RegisterSchema>) => {
const validatedFields = RegisterSchema.safeParse(values)
console.log(validatedFields.data)
if (!validatedFields.success) {
return { error: '入力内容を修正してください' }
}
return { error: 'エラーが発生しました' }
}
'use server'
と定義することでサーバー側で呼び出されるようになります。
前回の記事でご紹介したZodを使って取得した内容のバリデーションを行います。
Zodが便利なのはクライアントサイドだけでなくサーバーサイドでも同じように扱える点です。
受け取った値values
に対してバリデーションをし、エラーが発生した場合は、
エラーメッセージを呼び出したクライアントに返すことができます。
今回は、クライアントサイドでも同じバリデーションを施しているため基本的には入力内容を修正してください
のメッセージを返すことはありません。
なのでこの処理はスルーして最後のreturnでユーザーにメッセージを返します。
検証のため、今の設定では100%エラーが返るサーバーアクションとなります(後ほど修正します)
クライアントサイドでサーバーアクションを呼び出すよう設定
それでは作成したサーバーアクションを早速呼び出すようアカウント登録画面を修正していきます。
+ import { register } from '@/actions/register'
(※一部省略)
- const onSubmit = (values: z.infer<typeof RegisterSchema>) => {
+ const onSubmit = async (values: z.infer<typeof RegisterSchema>) => {
+ const response = await register(values)
- console.log(values)
+ console.log(response)
}
サーバアクションは非同期処理に設定していますのでonSubmit
でサーバアクションを呼び出す際にasync
をつけるのをお忘れなく。
サーバーアクションを呼び出した後にレスポンスをコンソールログで確認します。
アカウント登録画面で入力しボタンをクリックするとクライアントサイドではサーバーアクションのレスポンスが表示され、
サーバーサイドでは入力フォームの内容が表示されるかと思います。
このような表示となっていればOKです。
入力フォームの内容をサーバーサイドに渡すことができました。
サーバーアクションでの処理結果をユーザーに通知する
現状だとコンソールログにサーバーアクションの処理結果が表示されていますので、入力フォームに表示しアカウント作成が上手くいったか、失敗したかを通知させます。
実装としては大きく3段階に分けておこなっていきます。
- ①通知用のコンポーネント作成
- ②入力フォームにコンポーネントをセット
- ③サーバーアクションのレスポンスをもとに
onSubmit
を修正して通知用コンポーネントを表示
①通知用のコンポーネント作成
サーバーアクションが成功した場合、失敗した場合それぞれのコンポーネントを作成します。
import { CheckCircledIcon } from '@radix-ui/react-icons'
interface FormSuccessProps {
message?: string
}
export const FormSuccess = ({ message }: FormSuccessProps) => {
if (!message) return null
return (
<div className="flex items-center gap-x-2 rounded-md bg-emerald-500/15 p-3 text-sm text-emerald-500">
<CheckCircledIcon className="size-4" />
<p>{message}</p>
</div>
)
}
import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
interface FormErrorProps {
message?: string
}
export const FormError = ({ message }: FormErrorProps) => {
if (!message) return null
return (
<div className="flex items-center gap-x-2 rounded-md bg-destructive/15 p-3 text-sm text-destructive">
<ExclamationTriangleIcon className="size-4" />
<p>{message}</p>
</div>
)
}
どちらのコンポーネントも基本的には同じ挙動でメッセージを受け取ったらコンポーネントを返す。
メッセージがなければ何も表示しないと言ったものとなります。
利用者に分かりやすくアイコンも使用していますが、@radix-ui/react-icons
は、shadcnを最初にインストールしたときに一緒に入ってくるアイコンセットとなります。
②入力フォームにコンポーネントをセット
次に作成したコンポーネントを入力フォームにセットします。
サーバーアクションのレスポンスに含まれるメッセージに関してはuseState
で状態管理します。
+ import { useState } from 'react'
+ import { FormError } from '../form-error'
+ import { FormSuccess } from '../form-success'
(※一部省略)
export const RegisterForm = () => {
+ const [error, setError] = useState<string | undefined>("")
+ const [success, setSuccess] = useState<string | undefined>("")
const form = useForm<z.infer<typeof RegisterSchema>>({
resolver: zodResolver(RegisterSchema),
defaultValues: {
email: '',
password: '',
name: '',
},
})
(※一部省略)
/>
</div>
+ <FormError message={error} />
+ <FormSuccess message={success} />
<Button type="submit" className="w-full">
アカウントを作成する
</Button>
</form>
onSubmit
を修正して通知用コンポーネントを表示
③サーバーアクションのレスポンスをもとに最後にonSubmit
を修正して、エラーが返る場合に入力フォームにエラー用のコンポーネントを表示できるよう設定します。
- import { useState } from 'react'
+ import { useState, useTransition } from 'react'
const onSubmit = async (values: z.infer<typeof RegisterSchema>) => {
- const response = await register(values)
- console.log(response)
+ setError('')
+ setSuccess('')
+ setTransition(async () => {
+ try {
+ const response = await register(values)
+ if (response.error) {
+ setError(response.error)
+ } else {
+ // setSuccess(response.success)
+ }
+ } catch (e) {
+ setError('エラーが発生しました')
+ }
+ })
}
(※一部省略)
- <Button type="submit" className="w-full">
+ <Button type="submit" className="w-full" disabled={isPending}>
アカウントを作成する
</Button>
onSubmit
の一番最初にメッセージの初期化を行います。前回のメッセージ内容が残っていますので消した上で、サーバーアクションの結果をもとに再びメッセージを格納します。
ReactのuseTransition
を使って、サーバーアクションの処理結果が返ってくるまでは、「アカウントを作成する」ボタンを非活性にしています。ユーザーが間違って2回ボタンを押すのを防止するためとなります。
また今回は実装しませんでしたが、Inputコンポーネントに対してもdisabled={isPending}
を設定しておくのもいいかと思います。
動作確認
再び、アカウント登録画面で入力しボタンをクリックするとエラーメッセージが表示されるかと思います。
サーバーアクションを呼び出し結果をユーザーに通知することができました。
さいごに
今回はサーバーアクションと連携し入力フォームの入力内容を渡す処理を作成しました。
また処理が失敗したと仮定してその結果を入力フォームに戻しつつユーザーに通知する仕組みも実装しました。
次回はサーバーアクションが受け取った内容をもとにデータベースに登録していく機能を実装していきます。合わせて、現在は100%エラーが返るサーバーアクションとなっているところをデータベースの登録処理結果に基づいてメッセージ内容を切り替えられるよう実装していきます。
次の記事はこちら
関連する弊社の支援サービス
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
関連する技術ブログ
キャッシュ戦略完全ガイド:CDN・Redis・API最適化でパフォーマンスを最大化
Webアプリの高速化には、適切なキャッシュ戦略が不可欠。本記事では、CDN(Cloudflare / AWS CloudFront)による静的コンテンツ配信、Redis / Memcached を活用したデータベース負荷軽減、APIレスポンスキャッシュ(GraphQL / REST API)など、キャッシュを駆使してパフォーマンスを向上させる方法を解説。TTL設定、Next.js ISR / SSG のプリフェッチ、クエリキャッシュ(React Query / Apollo Client)、キャッシュヒット率の分析など、実践的なノウハウも紹介します。
shinagawa-web.com
チャットアプリ(画像・PDF送信、ビデオ通話機能付き)
お客様固有の要件を除き一般的なチャットアプリに求められる最低限の機能を実装しデモアプリとしてご紹介いたします。
shinagawa-web.com
React × Tailwind CSS × Emotionで実践するコンポーネント設計ガイド:デザインシステム・状態管理・再利用性の最適解
React、Tailwind CSS、Emotion、Storybook、Figma、Next.jsを活用したコンポーネント設計のベストプラクティスを紹介。デザインシステムに基づく命名規則、適切な状態管理、再利用性を高める抽象化、アクセシビリティ対応、スタイルガイドラインの整備、テーマ設定、バージョン管理、ドキュメント作成まで、モダンフロントエンド開発に欠かせない知識を徹底解説します。
shinagawa-web.com
管理ダッシュボード機能(グラフ表示、データ取り込み)
一般的な家計簿アプリとして求められる最低限の機能を実装しデモアプリとしてご紹介いたします。
shinagawa-web.com
Next.jsとAuth.jsで認証機能を実装するチュートリアル
Next.jsでアプリケーションを作る時に必要となる認証機能をどのように実装するかをご紹介する記事となります。アカウント登録から始まり、ログイン、ログアウト、ページごとのアクセス制御、OAuth、二要素認証、パスワードリセットなど認証に関連する様々な機能をコードベースでご紹介します。
shinagawa-web.com
10分で完成。AWS Amplify公式テンプレートを使ったNext.jsアプリの簡単デプロイ手順
AWS Amplifyの公式テンプレートを活用し、Next.jsアプリを素早く効率的にデプロイする方法をわかりやすく解説します。テンプレートの導入からコード修正後の再デプロイまで、初心者にも実践しやすい完全ガイドです。
shinagawa-web.com
Next.js × AWS CDK の統合環境構築:Docker でローカル開発から本番デプロイまで
Next.js と AWS CDK を1つのリポジトリで管理し、Docker を活用してローカル開発環境と本番環境向けのイメージを構築する方法を解説。ディレクトリ構成の設計から、Next.js のセットアップ、Docker Compose による開発環境の構築、ECR 向けの本番用 Docker イメージの作成、CDK の導入までを網羅。
shinagawa-web.com
Next.jsでのメール認証処理の実装ガイド:アカウント登録からトークン検証まで
Next.jsを活用したメール認証の実装方法を解説。アカウント登録時のトークン発行から、Sendgridを使ったメール送信処理まで、具体的な手順を紹介します。
shinagawa-web.com
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要なSaaSの乱立、開発工数の増加――これらの課題に悩んでいませんか?本サービスでは、クラウドコストの最適化、開発効率向上、技術選定の最適化 を通じて、単なるコスト削減ではなく、ROIを最大化する最適解 をご提案します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
開発生産性を最大化するための支援サービス
開発チームの生産性向上、コードの品質管理、インフラの最適化まで、様々な側面からサポートします。コードベースのリファクタリングから、テスト自動化、オンボーディング強化まで、プロジェクトの成功に必要なすべての支援を提供。御社の開発現場が効率的に機能するように、技術的な障害を取り除き、スムーズな開発を実現します。
shinagawa-web.com
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
Webアプリのセキュリティ強化支援
Webアプリの脆弱性対策からインフラのセキュリティ強化まで、包括的なセキュリティ支援を提供。OWASP Top 10対策、JWT認証の最適化、APIのアクセス制御、依存パッケージの監査、セキュアコーディングの標準化など、実践的なアプローチで開発現場の安全性を向上させます。
shinagawa-web.com
目次
お問い合わせ