【问题标题】:react-hook-form handling server-side errors in handleSubmitreact-hook-form 处理handleSubmit中的服务器端错误
【发布时间】:2021-02-04 17:44:59
【问题描述】:

我很难弄清楚如何处理不一定与 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."
                }
            ]
        }
    ]
}

【问题讨论】:

    标签: reactjs typescript react-hook-form


    【解决方案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 回答的启发,我完成了以下 hack s.t. usernamepassword 输入的更改将删除单个错误。

      如果您的错误与表单中的多个字段相关,则此 hack 无法很好地扩展,但它适用于登录用例。

      提交:

      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.passworderrors.username 上设置和呈现错误,当用户更新其中任何一个字段时,错误就会消失。

      【讨论】:

      • 可以通过规范服务器返回的错误信息,去掉错误处理中的if-else分支。您不应该为每个字段手动设置错误。有关更多详细信息,请参阅我的答案中的现场演示。
      • @NearHuscarl - 不确定你的意思,但if(successCaseResult){success handle} else if(error){error handle}awaited 调用的错误处理模式。 See here for more info
      猜你喜欢
      • 2021-11-21
      • 1970-01-01
      • 2023-01-22
      • 2011-07-24
      • 2017-03-15
      • 2017-01-10
      • 2015-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多