【4日目】React初学者が1週間でどこまで出来るか挑戦(Createフォーム作成)

はじめに

React学習1週間チャレンジ4日目です。Inertiaを活用してCreateフォーム、Store処理の実装までできました。平日仕事終わりはやる気はあるんですが完全に眠気との戦いです。

前回の振り返り:

Createフォームを作る

InertiaのuseFromメソッド

InertiaのFormヘルパuseFormが使うのが簡単らしい。

参考: Forms - Inertia.js

まずはuserFormの理解を深める。

import { useForm } from '@inertiajs/react'

const { data, setData, post, processing, errors } = useForm({
  email: '',
  password: '',
  remember: false,
})

分割代入構文

まずこの記法を理解できなかったため、JavaScriptの分割代入 (Destructuring assignment) 構文について調べた。

オブジェクトからプロパティを取り出して別個の変数に代入できる。プロパティの名前に基づいてバインドされるためプロパティ順番は入れ替えてもOK。

// Example
const object = {name: 'Ryosuke', like: 'Coffee'};

const {name, like} = object;

console.log(name); // Ryosuke
console.log(like); // Coffee

Inertiaのコードを再度見ると、useFormInertiaFormPropsオブジェクトを返しており、そのオブジェクトに定義されたdataオブジェクトやsetDataなどを分割代入していたということだ。

const { data, setData, post, processing, errors } = useForm({ ... });

フォームを作る

次に、フォームを送信するためにsubmitという関数を定義する。上記で定義されたpostの第一引数にURLを指定する。

const submit = (e) => {
    e.preventDefault();
    post('/users/store')
};

あとは入力用Inputを作る。

return (
    <>
        <h1 className="title title-h1">User 登録</h1>
        <form onSubmit={submit}>
            <input type="text"
                name=""
                value={data.name}
                className='input-field'
                onChange={(e) => setData('name', e.target.value)}
                required
            />
            <div className='invalid-feedback'>{errors.name}</div>

            {/* 他のInputは省略 */}

            <button className='btn btn-store'>
                登録
            </button>
        </form>
    </>
);

ポイントは、

  1. onSubmit={submit}: フォームが送信されたときにsubmit関数を呼び出すように設定。submit関数の中で、e.preventDefault();が呼び出されることで、フォームのデフォルトの送信動作(ページのリロード)がキャンセルされ、代わりにpost('/users/store')が実行される。
  2. value={data.name}: input要素の現在の値をdata.nameにバインドしている。フォームの状態(dataオブジェクト)とinput要素の表示が同期される。inputフィールドが入力されると、その値はdata.nameに反映される。
  3. onChange={(e) => setData('name', e.target.value)}: input要素の値が変更されるたび(ユーザーがテキストを入力/編集するたび)に実行されるイベントハンドラー。具体的には、入力された新しい値e.target.valuesetData関数を使ってdata.nameにセット。これにより、ユーザーの入力がdataオブジェクトに即座に反映される。
  4. {errors.name}: nameフィールドに関連するエラーメッセージを表示する。nameフィールドにバリデーションエラーなどがあればerrors.nameに格納される。
  5. disabled={processing}: processingはフォームが送信中の間はtrueを返す。 disabledがtrueの時HTMLのdisabled属性が有効になってボタンを無効にしている。 参考: input– React

送信されたリクエストをもとにユーザーデータを作成する方法は、通常のLaravel側の処理を書くだけ。

// UserController
public function store(UserStoreRequest $request)
{
    $user = User::create([
        'name'      => $request->input('name'),
        'email'     => $request->input('email'),
        'password'  => Hash::make($request->input('password')),
    ]);

    return to_route('users.index');
}

Formへルパの活用

InertiaのFormへルパの使い方を少し見ていきます。

isDirtyはフォームに変更がある場合にtrueを返す。これを使えば、フォームに変更が加わるまでは登録ボタンをdisabledにしておくことができる。

const { isDirty } = useForm({ ... })

<button className='btn btn-store' disabled={!isDirty}>
    登録
</button>

wasSuccessfulプロパティはフォーム送信成功時にtrueを返す。これを使えば登録成功アラートを出すことができる。

const { wasSuccessful } = useForm({})
{wasSuccessful && <div className="alert alert-success">登録成功</div>}

ただ、今回はサーバー側で登録処理完了後にroute('users.index)'へリダイレクトさせるため不要。

連載記事

  1. 【1日目】React初学者が1週間でどこまで出来るか挑戦
  2. 【2日目】React初学者が1週間でどこまで出来るか挑戦(ひたすらドキュメント編)
  3. 【3日目】React初学者が1週間でどこまで出来るか挑戦(Inertiaの理解)
  4. 【4日目】React初学者が1週間でどこまで出来るか挑戦(Createフォーム作成)
  5. 【5日目】React初学者が1週間でどこまで出来るか挑戦(Createフォーム改善)