Formik 表单中无法识别 handleSubmit 和值
handleSubmit and values not recognized in Formik form
我正在尝试使用 formik 创建登录表单。我对如何触发 handleSubmit 函数来调用登录 api 让用户登录感到困惑。我一直在 onSubmit 中调用 handleSubmit,但它无法识别 ValidatedLoginForm.js 文件中我的 codesandbox 中第 10 行和第 11 行的 onSubmit 方法中的值和 handleSubmit。我究竟应该在哪里调用 handleSubmit 并让用户登录到我的网站?
我的代码看起来像这样:
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;
我还会将 validationSchema 移出您的组件。使 read/understand 更容易,而且不必每次都重新创建。
我正在尝试使用 formik 创建登录表单。我对如何触发 handleSubmit 函数来调用登录 api 让用户登录感到困惑。我一直在 onSubmit 中调用 handleSubmit,但它无法识别 ValidatedLoginForm.js 文件中我的 codesandbox 中第 10 行和第 11 行的 onSubmit 方法中的值和 handleSubmit。我究竟应该在哪里调用 handleSubmit 并让用户登录到我的网站?
我的代码看起来像这样:
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;
我还会将 validationSchema 移出您的组件。使 read/understand 更容易,而且不必每次都重新创建。