【问题标题】:handleSubmit and values not recognized in Formik form在 Formik 表单中无法识别 handleSubmit 和值
【发布时间】:2020-05-01 06:13:27
【问题描述】:

我正在尝试使用 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;

【问题讨论】:

    标签: reactjs formik


    【解决方案1】:

    您目前正在onSubmit 代码中创建一个永远不会被调用的新函数。提交表单时调用函数values =&gt; { ... },但在该函数中创建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;
    

    我还将validationSchema 移出您的组件。使其更易于阅读/理解,并且不必每次都重新创建。

    【讨论】:

    • 谢谢。那行得通。顺便说一句,当我单击文本字段时,文本字段周围的中上边框就消失了。知道为什么会这样吗?
    • 是的,你styles.css中的css里面有label, input { display: block; width: 100%; },这使得所有标签100%。因此,当它向上移动时,标签的宽度会不正确。
    • 是的,现在没有空格了。感谢您的帮助
    猜你喜欢
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 2021-11-01
    • 2023-01-24
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多