inertia.jsのformをちゃんとやる
大前提
inertia.jsではformヘルパーを使う事がほぼほぼだ。これはlaravelとの相性がバツグンに作られている。たとえばerrorを掴まえたりとかそういうような事はほぼできてしまう。なお、これを使う場合はformタグを使う。まあちょっと例を見ていこう。
一番シンプルなフォーム
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import { Head, router } from '@inertiajs/react'
import { useState } from 'react'
import PrimaryButton from '@/Components/PrimaryButton';
export default function DemoForms({ auth }) {
const submit = (e) => {
e.preventDefault();
};
return (
<AuthenticatedLayout
user={auth.user}
header={
<h2 className="font-semibold text-xl text-gray-800 leading-tight">
DemoForm
</h2>
}
>
<Head title="DemoForm" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 text-gray-900">
<form onSubmit={submit}>
<PrimaryButton>Send</PrimaryButton>
</form>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
)
}
ここでは便宜的にPrimaryButton コンポーネントを使ったが別に<button>でもいい。見た目の問題だ。これにより以下のような見た目が提供されるだろう。
パーツを置いていく
といってもここではinput type="text"のみをおく。あとpostとかもろもろ付けたので全文載せておく
import { useState } from 'react'
import PrimaryButton from '@/Components/PrimaryButton';
export default function DemoForms({ auth }) {
const { post } = useForm();
const submit = (e) => {
e.preventDefault();
post(route('demoforms.store'));
};
return (
<AuthenticatedLayout
user={auth.user}
header={
<h2 className="font-semibold text-xl text-gray-800 leading-tight">
DemoForm
</h2>
}
>
<Head title="DemoForm" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 text-gray-900">
<form onSubmit={submit}>
<input type="text" name="message" />
<PrimaryButton>Send</PrimaryButton>
</form>
</div>
</div>
</div>
</div>
</AuthenticatedLayout>
)
}
さて、これで
こんなのを入力でき、かつsubmitの送信先を
post(route('demoforms.store'));
このrouteにした。これはlaravelのrouteと同じだからちゃんと設定しておく。laravelのcontrollerでは以下のようにとりあえずrequest dumpして終わる
public function store(Request $request)
{
dd($request->all());
}
そうすると「あああ」とか入力したdumpは
となる、要するに空というわけだ。
dataとsetDataの使用
以下のように定義する
const { post } = useForm({
message: '',
});
これで送信すると少なくとも
このようにmessageキーは付くようになった。実際にこのdataに値をsetするのがsetDataであり、以下のように使う
const { post, setData } = useForm({
message: '',
});
で、formでは
<form onSubmit={submit}>
<input type="text" name="message"
onChange={e => setData('message', e.target.value)}
/>
<PrimaryButton>Send</PrimaryButton>
</form>
こんな風にして使う、すると
このようにレシーブできるはずだ。
フォーム完了の処理
本来は
public function store(Request $request)
{
dd($request->all());
}
このddでDBに保存したりするだろうが、ここでは行わない。とりあえず何かやって戻すのが、inertia.jsの基本であり、これは従来型のhttpのpostと同じノリだろう。
public function store(Request $request): RedirectResponse
{
// データー更新処理
return redirect(route('demoforms.index'));
}
これでデーターが更新されていくはずだ(本来は)
ただ、ここでSendを押しても何も変わらない
これは実際に画面遷移を行っていないからであり、この状態だと何なんだかよくわからんので、処理が成功した時はonSuccessを走らせるとよい。
const submit = (e) => {
e.preventDefault();
post(route('demoforms.store'), { onSuccess: () => alert("ok") } );
};
resetとdata
実際のところalertを出しても意味がないからformを抹消するとする。これはresetをuseFormから呼び出す
const { post, setData, reset } = useForm({
message: '',
});
const submit = (e) => {
e.preventDefault();
post(route('demoforms.store'), { onSuccess: () => reset() } );
};
じゃあこれでresetされんのか?
<form onSubmit={submit}>
<input type="text" name="message"
onChange={e => setData('message', e.target.value)}
/>
<PrimaryButton>Send</PrimaryButton>
</form>
というとリセットされない。なぜならこのresetはuseFormのdata部分を空にするという挙動だからであーる。つまりvalueをuseFormのdataに合わせる必要がある。やってみよう。
dataにアクセスする場合はdata変数も呼びこまないといけない。
const { post, setData, reset, data } = useForm({
message: '',
});
これにより
<form onSubmit={submit}>
<input type="text" value={data.message}
onChange={e => setData('message', e.target.value)}
/>
<PrimaryButton>Send</PrimaryButton>
</form>
このようにvalueを正しくdataからひっぱってこれるようになり、resetが機能するようになる。つまりresetとはuseFormのdataを抹消することともいえる。
その他の便利なメソッド郡
processing
これはやはり便利がよくて、以下のように通常利用される
const { post, setData, reset, data, processing } = useForm({
message: '',
});
これで代入しておいての
<form onSubmit={submit}>
<input type="text" value={data.message}
onChange={e => setData('message', e.target.value)}
/>
<PrimaryButton disabled={processing}>Send</PrimaryButton>
</form>
こんな感じ。これはform送信中はtrueになるというもので、たとえば長い処理をシュミレートする
public function store(Request $request): RedirectResponse
{
sleep(5);
return redirect(route('demoforms.index'));
}
このような時、とりわけ威力を発揮するだろう
この記事が気に入ったらサポートをしてみませんか?