我正在学习react,我决定创建一个连接后端Express.js的react前端。目前,我正在尝试在我的注册/登录表单上添加验证。我真的不明白验证系统是如何实现的。我注意到教程使用了Formik/Yup的功能组件,但是,我使用的是基于类的组件。
当我尝试渲染它时,我的注册页面没有显示任何内容。当然,我一定是实现错误了,我不知道该怎么办。谢谢你的帮助。
import React, { Component } from "react";
import { register } from "./UserFunctions";
import { Formik, Field } from "formik";
import * as Yup from "yup";
// const validationSchema = yup.object().shape({
// first_name: yup.string
// })
class Register extends Component {
constructor() {
super();
this.state = {
first_name: "",
last_name: "",
email: "",
password: "",
errors: {},
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
onSubmit(e) {
e.preventDefault();
//new user object
const newUser = {
first_name: this.state.first_name,
last_name: this.state.last_name,
email: this.state.email,
password: this.state.password,
};
//if register function succesful, redirect to login page
register(newUser).then((res) => {
this.props.history.push(`/login`);
});
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx-auto">
<Formik
initialValues={{
first_name: "",
last_name: "",
email: "",
password: "",
}}
validationSchema={Yup.object().shape({
first_name: Yup.string()
.required("First Name is Required.")
.min(1, "First Name is Too Short."),
last_name: Yup.string()
.required("Last Name is Required.")
.min(1, "Last Name is Too Short."),
email: Yup.string().email().required("Email is 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 {
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
} = props;
<form noValidate onSubmit={this.onSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Register</h1>
<div className="form-group">
<label htmlFor="name">First name</label>
<input
type="text"
className="form-control"
name="first_name"
placeholder="Enter your first name"
value={this.state.first_name}
onChange={this.onChange}
/>
{errors.first_name && touched.first_name && (
<div className="input-feedback">{errors.first_name}</div>
)}
</div>
<div className="form-group">
<label htmlFor="name">Last name</label>
<input
type="text"
className="form-control"
name="last_name"
placeholder="Enter your last name"
value={this.state.last_name}
onChange={this.onChange}
/>
{errors.last_name && touched.last_name && (
<div className="input-feedback">{errors.last_name}</div>
)}
</div>
<div className="form-group">
<label htmlFor="email">Email address</label>
<input
type="email"
className="form-control"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.onChange}
/>
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
placeholder="Password"
value={this.state.password}
onChange={this.onChange}
/>
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
</div>
<button
type="submit"
className="btn btn-lg btn-primary btn-block"
>
Register!
</button>
</form>;
}}
</Formik>
</div>
</div>
</div>
);
}
}
export default Register;
Formik在尝试提交时验证表单,如果有任何错误,它不允许提交表单,当用户尝试提交错误时,您可以向他显示错误消息,请参阅此页面以供参考
这是一个带有功能组件的代码,代码行更少,可以像预期的一样工作
import React from "react";
import { useFormik } from "formik";
import { register } from "./UserFunctions";
import * as Yup from "yup";
const Register = ({ history }) => {
const validationSchema = Yup.object().shape({
first_name: Yup.string()
.required("First Name is Required.")
.min(1, "First Name is Too Short."),
last_name: Yup.string()
.required("Last Name is Required.")
.min(1, "Last Name is Too Short."),
email: Yup.string().email().required("Email is 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."),
});
const formik = useFormik({
initialValues: {
first_name: "",
last_name: "",
email: "",
password: "",
},
validationSchema: validationSchema,
onSubmit: (values) => {
const newUser = {
first_name: values.first_name,
last_name: values.last_name,
email: values.email,
password: values.password,
};
//if register function succesful, redirect to login page
register(newUser).then((res) => {
history.push(`/login`);
});
},
});
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx-auto">
<form noValidate onSubmit={formik.handleSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Register</h1>
<div className="form-group">
<label htmlFor="name">First name</label>
<input
type="text"
className="form-control"
name="first_name"
placeholder="Enter your first name"
value={formik.values.first_name}
onChange={formik.handleChange}
/>
{formik.errors.first_name && formik.touched.first_name && (
<div className="input-feedback">{formik.errors.first_name}</div>
)}
</div>
<div className="form-group">
<label htmlFor="name">Last name</label>
<input
type="text"
className="form-control"
name="last_name"
placeholder="Enter your last name"
value={formik.values.last_name}
onChange={formik.handleChange}
/>
{formik.errors.last_name && formik.touched.last_name && (
<div className="input-feedback">{formik.errors.last_name}</div>
)}
</div>
<div className="form-group">
<label htmlFor="email">Email address</label>
<input
type="email"
className="form-control"
name="email"
placeholder="Enter email"
value={formik.values.email}
onChange={formik.handleChange}
/>
{formik.errors.email && formik.touched.email && (
<div className="input-feedback">{formik.errors.email}</div>
)}
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
placeholder="Password"
value={formik.values.password}
onChange={formik.handleChange}
/>
{formik.errors.password && formik.touched.password && (
<div className="input-feedback">{formik.errors.password}</div>
)}
</div>
<button type="submit" className="btn btn-lg btn-primary btn-block">
Register!
</button>
</form>
;
</div>
</div>
</div>
);
};
export default Register;
- 首先,在使用表单库时不需要使用state。使用Form库的主要目的是封装状态并减少样板
- Formik本身就是表单状态的容器
- 请注意:-您应该使用formik提供的
values
(包含您的表单数据(和handleChange
将formik表单数据的值传递到输入字段中 -
Formik将
onSubmit
作为一个道具,您可以在这里获得验证后的表单状态,然后在这里注册新用户
此外,您可以在此处查看codesandbox链接。
import React, { Component } from "react";
// import { register } from "./UserFunctions";
import { Formik } from "formik";
import * as Yup from "yup";
const schema = Yup.object().shape({
first_name: Yup.string()
.required("First Name is Required.")
.min(1, "First Name is Too Short."),
last_name: Yup.string()
.required("Last Name is Required.")
.min(1, "Last Name is Too Short."),
email: Yup.string().email().required("Email is 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.")
});
class Register extends Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx-auto">
<Formik
initialValues={{
first_name: "",
last_name: "",
email: "",
password: ""
}}
validationSchema={schema}
// tell the formik to validate onBlur
validateOnBlur
onSubmit={(values) => {
// here you have the access to the form data
// values.first_name, values_last_name, values_email, values_password
//if register function succesful, redirect to login page
// register(values).then((res) => {
// this.props.history.push(`/login`);
// })
}}
>
{(props) => {
const {
touched,
errors,
handleSubmit,
values,
handleChange,
handleBlur,
} = props;
return (
<form noValidate onSubmit={handleSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Register</h1>
<div className="form-group">
<label htmlFor="name">First name</label>
<input
type="text"
className="form-control"
name="first_name"
placeholder="Enter your first name"
value={values.first_name}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.first_name && touched.first_name && (
<div className="input-feedback">
{errors.first_name}
</div>
)}
</div>
<div className="form-group">
<label htmlFor="name">Last name</label>
<input
type="text"
className="form-control"
name="last_name"
placeholder="Enter your last name"
value={values.last_name}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.last_name && touched.last_name && (
<div className="input-feedback">{errors.last_name}</div>
)}
</div>
<div className="form-group">
<label htmlFor="email">Email address</label>
<input
type="email"
className="form-control"
name="email"
placeholder="Enter email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
placeholder="Password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
</div>
<button
type="submit"
className="btn btn-lg btn-primary btn-block"
>
Register!
</button>
</form>
);
}}
</Formik>
</div>
</div>
</div>
);
}
}
export default Register;
import React from "react";
import { Helmet } from "react-helmet";
import { Formik } from "formik";
import * as Yup from "yup";
import axios from "axios";
import "./Add.scss";
import Header from "../../components/Header"
import { toast, Toaster } from "react-hot-toast";
export default function Add() {
return (
<>
<Helmet>
<title>Add</title>
</Helmet>
<Header/>
<div className="formik">
<div className="form">
<Formik
initialValues={{
title: "",
price: "",
image: "",
desc: "",
}}
validationSchema={Yup.object({
title: Yup.string().required("title is required"),
price: Yup.number().required("price is required"),
image: Yup.string().required("image is required"),
desc: Yup.string().required("desc is required"),
})}
onSubmit={(values, { resetForm }) => {
axios.post("http://localhost:8080/robots", values).then((res) => {
toast.success("Added new Card");
});
resetForm();
}}
>
{({ values, handleChange, handleSubmit, dirty }) => (
<form onSubmit={handleSubmit}>
<label htmlFor="title" onSubmit={handleSubmit}>
title:
</label>
<input
type="text"
placeholder="title"
id="title"
value={values.title}
onChange={handleChange}
/>
<label htmlFor="price">Price:</label>
<input
type="number"
placeholder="price"
id="price"
value={values.price}
onChange={handleChange}
/>
<label htmlFor="image">image:</label>
<input
type="text"
placeholder="image"
id="image"
value={values.image}
onChange={handleChange}
/>
<label htmlFor="desc">Description:</label>
<input
type="text"
placeholder="desc"
id="desc"
value={values.desc}
onChange={handleChange}
/>
<button type="submit" disabled={!dirty}>
Add
</button>
</form>
)}
</Formik>
</div>
</div>
<Toaster />
</>
);
}