reactjs - مدیریت خطاهای سمت سرور در handleSubmit با react-hook-form


من در تلاش برای فهمیدن چگونگی مدیریت خطاهایی هستم که لزوماً به یک فیلد ورودی خاص در 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."
                }
            ]
        }
    ]
}

پاسخ شماره ۱

برای نمایش خطا از سرور به کاربر خود، شما نیاز دارید از:

  • از 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>

نسخه نمایشی زنده

پاسخ شماره ۲

الهام گرفته از پاسخ @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، خطا هنگامی که کاربر هر یک از این فیلدها را بهروزرسانی کند، ناپدید خواهد شد.