ウェブサイト検索

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 の両方に設定してレンダリングすることにより、ユーザーがどちらかのフィールドを更新するとエラーは消えます。

関連記事