reactjs - 在 Formik 表单中无法识别 handleSubmit 和值

标签 reactjs formik

我正在尝试使用 formik 创建登录表单。我对如何触发 handleSubmit 函数来调用登录 api 以供用户登录感到困惑。我一直在 onSubmit 中调用 handleSubmit,但它无法识别 ValidatedLoginForm.js 文件中我的代码和框中第 10 行和第 11 行的 onSubmit 方法中的值和 handleSubmit。我在哪里确切地调用 handleSubmit 并让用户登录到我的网站?

my codesandbox

我的代码看起来像这样:

import React, { useState } from "react";
import { Formik } from "formik";
import TextField from "@material-ui/core/TextField";
import * as Yup from "yup";

const ValidatedLoginForm = props => (
  <Formik
    initialValues={{ email: "", password: "" }}
    onSubmit={values => {
      const handleSubmit = async event => {
        event.preventDefault();

        var body = {
          password: password,
          email: email
        };
        console.log(body);
        const options = {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json"
          },
          body: JSON.stringify(body)
        };
        const url = "/api/authenticate";
        try {
          const response = await fetch(url, options);
          const text = await response.text();

          if (text === "redirect") {
            props.history.push(`/editor`);
          } else if (text === "verifyemail") {
            props.history.push(`/verifyOtp/${this.state.email}`);
          } else {
            console.log("login failed");
            window.alert("login failed");
          }
        } catch (error) {
          console.error(error);
        }
      };
    }}
    //********Using Yup for validation********/

    validationSchema={Yup.object().shape({
      email: Yup.string()
        .email()
        .required("Required"),
      password: Yup.string()
        .required("No password provided.")
        .min(8, "Password is too short - should be 8 chars minimum.")
        .matches(/(?=.*[0-9])/, "Password must contain a number.")
    })}
  >
    {props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;
      return (
        <>
          <form onSubmit={handleSubmit} noValidate>
            <TextField
              variant="outlined"
              margin="normal"
              required
              fullWidth
              id="email"
              value={values.email}
              label="Email Address"
              name="email"
              autoComplete="email"
              autoFocus
              onChange={handleChange}
              onBlur={handleBlur}
              className={errors.email && touched.email && "error"}
            />
            {errors.email && touched.email && (
              <div className="input-feedback">{errors.email}</div>
            )}
            <TextField
              variant="outlined"
              margin="normal"
              required
              fullWidth
              name="password"
              value={values.password}
              label="Password"
              type="password"
              id="password"
              onBlur={handleBlur}
              autoComplete="current-password"
              className={errors.password && touched.password && "error"}
              onChange={handleChange}
            />

            {errors.password && touched.password && (
              <div className="input-feedback">{errors.password}</div>
            )}
            <button type="submit" disabled={isSubmitting}>
              Login
            </button>
          </form>
        </>
      );
    }}
  </Formik>
);

export default ValidatedLoginForm;

最佳答案

您目前正在 onSubmit 中创建一个新函数永远不会被调用的代码。函数values => { ... }在提交表单时调用,但在该函数中您创建 handleSubmit并且永远不会调用它。

如果移动创建handleSubmit一点点,这一切都变得更容易阅读。这将变成类似

import React, { useState } from "react";
import { Formik } from "formik";
import TextField from "@material-ui/core/TextField";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";

const ValidatedLoginForm = props => {
  // The function that handles the logic when submitting the form
  const handleSubmit = async values => {
    // This function received the values from the form
    // The line below extract the two fields from the values object.
    const { email, password } = values;
    var body = {
      password: password,
      email: email
    };
    console.log(body);
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const text = await response.text();

      if (text === "redirect") {
        props.history.push(`/editor`);
      } else if (text === "verifyemail") {
        props.history.push(`/verifyOtp/${this.state.email}`);
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  // Returning the part that should be rendered
  // Just set handleSubmit as the handler for the onSubmit call.
  return (
    <Formik
      initialValues={{ email: "", password: "" }}
      onSubmit={handleSubmit}
      //********Using Yup for validation********/

      validationSchema={Yup.object().shape({
        email: Yup.string()
          .email()
          .required("Required"),
        password: Yup.string()
          .required("No password provided.")
          .min(8, "Password is too short - should be 8 chars minimum.")
          .matches(/(?=.*[0-9])/, "Password must contain a number.")
      })}
    >
      {props => {
        const {
          values,
          touched,
          errors,
          isSubmitting,
          handleChange,
          handleBlur,
          handleSubmit
        } = props;
        return (
          <>
            <form onSubmit={handleSubmit} noValidate>
              <TextField
                variant="outlined"
                margin="normal"
                required
                fullWidth
                id="email"
                value={values.email}
                label="Email Address"
                name="email"
                autoComplete="email"
                autoFocus
                onChange={handleChange}
                onBlur={handleBlur}
                className={errors.email && touched.email && "error"}
              />
              {errors.email && touched.email && (
                <div className="input-feedback">{errors.email}</div>
              )}
              <TextField
                variant="outlined"
                margin="normal"
                required
                fullWidth
                name="password"
                value={values.password}
                label="Password"
                type="password"
                id="password"
                onBlur={handleBlur}
                autoComplete="current-password"
                className={errors.password && touched.password && "error"}
                onChange={handleChange}
              />

              {errors.password && touched.password && (
                <div className="input-feedback">{errors.password}</div>
              )}
              <button type="submit" disabled={isSubmitting}>
                Login
              </button>
            </form>
          </>
        );
      }}
    </Formik>
  );
};

export default ValidatedLoginForm;

我也会将验证架构移出您的组件。使其更易于阅读/理解,并且不必每次都重新创建。

关于reactjs - 在 Formik 表单中无法识别 handleSubmit 和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59735137/

相关文章:

javascript - React setState 异步导致下拉延迟

javascript - 在 Formik Form 上更新 initialValues Prop 不会更新输入值

reactjs - 每当 React Formik 发生错误时,更改现有输入字段的样式

reactjs - 带有用于自定义 Prop 的样式化组件条件 css 的 typescript

javascript - 使用 React 显示图像

javascript - 将参数与字段数据一起传递给 onChange 事件上的函数

reactjs - 类型 'null' 不可分配给类型 'HTMLInputElement' ReactJs

javascript - React-Bootstrap表单切换按钮

javascript - 如何在 React/Formik Select 组件上显示占位符值?

javascript - 如何在禁用字段上停止yup验证?