reactjs - react-hook-formでhandleSubmit内のサーバー側エラーを処理する
私は、必ずしも単一の入力フィールドに関連しないエラーを react-hook-form でどのように扱うかを理解するのに苦労しています。言い換えると、handleSubmit のエラーをどのように扱えばよいのでしょうか?
例えば、次のような形式を持っている場合:
import to from 'await-to-js'
import axios, { AxiosResponse } from 'axios'
import React from "react"
import { useForm } from "react-hook-form"
type LoginFormData = {
username: string,
password: string,
}
export const Login: React.FC = () => {
const { register, handleSubmit } = useForm<LoginFormData>()
const onSubmit = handleSubmit(async (data) => {
const url = '/auth/local'
const [err, userLoginResult] = await to<AxiosResponse>(axios.post(url, data))
if (userLoginResult) {
alert('Login successful')
}
else if (err) {
alert('Bad username or password')
}
})
return (
<div className="RegisterOrLogIn">
<form onSubmit={onSubmit}>
<div>
<label htmlFor="username">username</label>
<input name="username" id="username" ref={register} />
</div>
<div>
<label htmlFor="password">Password</label>
<input type="password" id="password" name="password" ref={register} />
</div>
<button type="submit"> </button>
</form>
</div>
)
}
ユーザー名またはパスワードにエラーがあることをユーザーに知らせるための react-hook-form の方法はありますか? alert() 以外で
おそらく他の場所で答えが出ているのかもしれませんが、私はそれを見つけることができませんでした。
明確化 サーバーから受け取ったエラーは単一のフィールドに関するものではありません:
{
"statusCode": 400,
"error": "Bad Request",
"message": [
{
"messages": [
{
"id": "Auth.form.error.invalid",
"message": "Identifier or password invalid."
}
]
}
],
"data": [
{
"messages": [
{
"id": "Auth.form.error.invalid",
"message": "Identifier or password invalid."
}
]
}
]
}
回答 #1
サーバーからのエラーをユーザーに表示するには、次のものを使用する必要があります:
- サーバーがエラー応答を返したときに、プログラムでエラーを設定するために
setErrorを使用します。 - フォーム内のすべてのフィールドのエラー状態を取得してユーザーに表示するための
errors。
type FormInputs = {
username: string;
};
const { setError, formState: { errors } } = useForm<FormInputs>();
handleSubmit コールバック内で
axios
.post(url, data)
.then((response) => {
alert("Login successful");
})
.catch((e) => {
const errors = e.response.data;
if (errors.username) {
setError('username', {
type: "server",
message: 'Something went wrong with username',
});
}
if (errors.password) {
setError('password', {
type: "server",
message: 'Something went wrong with password',
});
}
});
あなたのコンポーネントで
<label htmlFor="username">username</label>
<input id="username" {...register("username")} />
<div>{errors.username && errors.username.message}</div>
ライブデモ
回答 #2
@NearHuscarl の回答に触発されて、次のハックを行いました。つまり、username または password の入力に変更があると、単一のエラーが削除されるようにしました。
このハックは、フォームの複数のフィールドに関連するエラーがある場合にはうまく拡張できませんが、ログインのユースケースではうまく機能しました。
送信時:
const onSubmit = handleSubmit(async (data) => {
const url = '/auth/local'
const [err, userLoginResult] = await to<AxiosResponse>(axios.post(url, data)) // see await-to-js
if (userLoginResult) {
alert('Login successful')
}
else if (err) {
const formError = { type: "server", message: "Username or Password Incorrect" }
// set same error in both:
setError('password', formError)
setError('username', formError)
}
})
コンポーネント:
return (
<div className="RegisterOrLogIn">
<form onSubmit={onSubmit}>
<div>
<label htmlFor="username">username</label>
<input name="username" id="username" ref={register} />
</div>
<div>
<label htmlFor="password">Password</label>
<input type="password" id="password" name="password" ref={register} />
</div>
<div>{errors.username && errors.password?.message /*note the cross check*/}</div>
<button type="submit"> </button>
</form>
</div>
)
エラーを errors.password と errors.username の両方に設定してレンダリングすることにより、ユーザーがどちらかのフィールドを更新するとエラーは消えます。