カテゴリー: FrontEnd

Inertia使ってみた②

はじめに

前回はInertiaの基本的な内容について書いてみました。今回はもう少し実践的内容という事で、Inertiaで用意しているフォームリクエスト周りの機能について紹介したいと思います。
前回同様に、Laravel+Reactの組み合わせです。

フォームヘルパー

Reactでフォームリクエストを実装する際は、useStateフックを使用して実装する事が多いと思いますが、Inertiaではフォームに特化したuseFormフックを使う事が出来ます。
Laravel Sailに含まれるサンプルログイン画面を参考にuseFormフックの使い方を見たいと思います。

export default function Login({status, canResetPassword}) {
    // useStateフックをラップしたuseForm
    const {data, setData, post, processing, errors, reset} = useForm({
        email: '',
        password: '',
        remember: '',
    });

    useEffect(() => {
        return () => {
            reset('password');
        };
    }, []);

    const onHandleChange = (event) => {
        setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value);
    };

    const submit = (e) => {
        e.preventDefault();
        post(route('login'));
    };

    return (
        <GuestLayout>
            <Head title="Log in"/>

            <form onSubmit={submit}>
                <div>
                    <InputLabel forInput="email" value="Email"/>
                    <TextInput id="email" type="email" name="email" value={data.email} className="mt-1 block w-full" autoComplete="username" isFocused={true} handleChange={onHandleChange}/>
                    <InputError message={errors.email} className="mt-2"/>
                </div>

                <div className="mt-4">
                    <InputLabel forInput="password" value="Password"/>
                    <TextInput id="password" type="password" name="password" value={data.password} className="mt-1 block w-full" autoComplete="current-password" handleChange={onHandleChange}/>
                    <InputError message={errors.password} className="mt-2"/>
                </div>

                <div className="block mt-4">
                    <label className="flex items-center">
                        <Checkbox name="remember" value={data.remember} handleChange={onHandleChange}/>
                        <span className="ml-2 text-sm text-gray-600">Remember me</span>
                    </label>
                </div>

                <div className="flex items-center justify-end mt-4">
                    <Link href={route('password.request')} className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                        Forgot your password?
                    </Link>

                    <PrimaryButton className="ml-4" processing={processing}>
                        Log in
                    </PrimaryButton>
                </div>
            </form>
        </GuestLayout>
    );
}

ポイント

上記例では、useFormで以下のような関数や値を使用しています。一般的なフォーム送信に必要な事項揃っているかと思います。

  • useState同様に、useForm() の引数に初期値を設定する。ここでは、email、password、rememberの3つでそれぞれ空白となっています。
  • 値更新の際もuseState同様に、setDataで更新する
  • post()関数だけでフォームデータをPOST通信しています。他に、get、put、delete、patchも用意されています。
  • 通信中かどうかをprocessingで判別出来ます。ここでは、通信中はログインボタンをdisableにして複数回クリック出来ないようにしています。
  • Controller側でバリデーションエラーが出た場合、フィールドとエラーメッセージがerrorsに含まれます。ここでは、InputErrorコンポーネントに渡してエラーの場合のみ、メッセージを赤字表示しています
  • resetで値をデフォルト値に戻す事が出来ます。。フィールド名を含めるとそのフィールドが消去され、何も指定しないと全ての値がデフォルト値に戻るようです。

他機能

他にも例便利な関数や値があるので一部紹介すると

transform関数を使い、送信前のフォームデータを編集する事が出来ます。

transform((data) => {
            // チェックボックスがチェックされていたら、trueの代わりに文字列の`on`を代入
            data.remember = data.remember ? 'on' : '';
            return data;
        })

フォーム送信が成否を判別するwasSuccessfulrecentlySuccessfulの値を見て通信結果を表示する事が出来ます。
通信が成功するとそれぞれtrueの値がセットされます。recentlySuccessfulは2秒間だけtrueがセットされるので、フラッシュメッセージ表示に利用出来ます。

<span>{wasSuccessful ? '通信が成功しました' : ''}</span>
<span>{recentlySuccessful ? '通信が成功しました(2秒間だけ表示される)' : ''}</span>

ローディング表示

Progressライブラリのラッパーが用意されています。
app.jsxファイルの設定で表示内容を変更する事が出来ます。

createInertiaApp({
  progress: {
    // プログレスバーが表示されるまでの時間(ミリ秒)
    delay: 250,

    // プログレスバー色
    color: '#29d',

    // Default NProgress stylesを使用するか
    includeCSS: true,

    // グルグル表示を行うかどうか
    showSpinner: false,
  },
  // ...
})

デフォルトの状態だとグルグル表示が画面右上に小さく表示されるだけなので、app.cssファイルにCSSを追加して表示を変更した方が良いかと思います。下は、画面中央に100pxサイズで表示する際の例です。

.nprogress-busy #nprogress {
    @apply bg-gray-200 opacity-50 top-0 left-0 fixed w-full h-full
}

.nprogress-busy #nprogress .spinner {
    @apply absolute top-1/2 right-1/2
}

.nprogress-busy #nprogress .spinner-icon {
    @apply w-[100px] h-[100px]
}

さいごに

useFormを利用する事でフォームデータの管理からフラッシュメッセージ表示まで一通りの事を簡潔に実装出来そうです。機会があれば使ってみてください。

おすすめ書籍

Yossy

シェア
執筆者:
Yossy
タグ: ReactInertia

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

3週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

1か月 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前