无法将错误从API响应传递到Formik错误显示

时间:2019-03-22 02:57:58

标签: javascript reactjs formik

我正在使用React,Formik和yup将数据提交到REST API。

我的React组件如下:

import React from "react";
import { render } from "react-dom";
import { Formik, Field, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
import { BrowserRouter } from "react-router-dom";

import App from "./App";

const ContactUsFormSchema = Yup.object().shape({
  givenName: Yup.string()
    .required("First name is required")
    .max(50, "Your first name must be 2 to 50 characters")
    .min(2, "Your first name must be 2 to 50 characters"),
  surname: Yup.string()
    .required("Your last name is required")
    .max(50, "Your last name must be 2 to 50 characters")
    .min(2, "Your last name must be 2 to 50 characters"),
  email: Yup.string()
    .email()
    .required("EMail address is required")
    .max(100, "Your email address can't be longer than 100 characters")
});

class Register extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <button
          id="home"
          onClick={() => this.loadHome()}
          className="square-button"
        >
          Home
        </button>

        <h1>SpringBoot/React OAuth2 Registration Page</h1>
        <Formik
          initialValues={{
            givenName: this.props.user.givenName,
            surname: this.props.user.surname,
            email: this.props.user.email,
            mobile: this.props.user.mobile
          }}
          validationSchema={ContactUsFormSchema}
          // on submit Formik will call this passing the values and actions; call the doSubmit method passing them and the form itself
          // Passing the form itself allows an action to be performed after the API call returns
          onSubmit={(values, actions) => this.doSubmit(values, actions, this)}
          // the render method returns the actual form; note each field has a corresponding error field
          render={({ errors, touched, isSubmitting }) => (
            <Form>
              First Name:
              <Field type="text" name="givenName" />
              <ErrorMessage name="givenName">
                {errorMessage => <div className="error">{errorMessage}</div>}
              </ErrorMessage>
              Last Name:
              <Field type="text" name="surname" />
              <ErrorMessage name="surname">
                {errorMessage => <div className="error">{errorMessage}</div>}
              </ErrorMessage>
              Email Address:
              <Field type="text" name="email" />
              <ErrorMessage name="email">
                {errorMessage => <div className="error">{errorMessage}</div>}
              </ErrorMessage>
              Mobile:
              <Field type="text" name="mobile" />
              <ErrorMessage name="mobile">
                {errorMessage => <div className="error">{errorMessage}</div>}
              </ErrorMessage>
              <p />
              {this.props.result}
              <button type="submit" disabled={isSubmitting}>
                Register
              </button>
            </Form>
          )}
        />
      </div>
    );
  }

  doSubmit = (values, actions, form) => {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST", "http://localhost:8080/register", true);
    xmlhttp.setRequestHeader("Accept", "application/json");
    xmlhttp.setRequestHeader("Authorization", window.sessionStorage.jwt);
    xmlhttp.setRequestHeader("Content-type", "application/json");
    xmlhttp.onreadystatechange = function() {
      // Function called when the state changes.
      if (xmlhttp.readyState === 4) {
        actions.setSubmitting(false);
        if (xmlhttp.status === 200) {
          render(
            <BrowserRouter>
              <App />
            </BrowserRouter>,
            document.getElementById("root")
          );
        } else if (xmlhttp.status === 400) {
          actions.setErrors(JSON.parse(xmlhttp.responseText).errors);
        }
      }
    };
    xmlhttp.send(JSON.stringify(values));
  };
}

export default Register;

API返回的JSON数据为

{
  "errorCode": "Validation failed",
  "errors": [
    {
      "errorMessage": "Phone numbers must consist of digits and spaces only with an optional + sign at the front",
      "field": "mobile"
    }
  ]
}

我真的非常陌生,更不用说React等JavaScript了,所以我对为什么错误没有按我期望的那样填充感到非常困惑,并希望得到任何人愿意提供的帮助。

1 个答案:

答案 0 :(得分:0)

您的errors数组(从API返回)不适合Formik的error模型。您要传递的对象应将字段名称作为键,并将某些字符串作为值。例如:

{
  givenName: 'First name is required',
  email:  "Your email address can't be longer than 100 characters"
}

在您的情况下,您可以通过以下方式将错误数组转换为对象:https://jsfiddle.net/Lg87jwpb/2/(提供了注释imperative way作为替代方法,以更好地了解其完成方式)。