React的表单组件-Formik和前端验证库-Yup的使用
推荐阅读
强烈推荐Formik官方教程,其实根据官方教程能完全解决Formik的使用。所以本篇文章只是记录下Formik的学习过程。更多详细内容请移步官方文档
一个简单的表单提交
初始代码
内容来自于官方文档中提供的基本代码
在initialValues中填写表单的每一项
import React from "react";
import ReactDOM from "react-dom";
import { useFormik } from "formik";
import "./styles.css";
const SignupForm = () => {
const formik = useFormik({
// 表单里的每一个表单项,在这里初始化
initialValues: {
firstName: "",
lastName: "",
email: ""
},
// 参数values为表单中所有value集合
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
}
});
return (
// onSubmit调用formik中handleSubmik,进而调用的是useFormik中的onSubmit函数
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
// onchange调用formik的handelChange
onChange={formik.handleChange}
// 当前表单的value值
value={formik.values.firstName}
/>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
<button type="submit">Submit</button>
</form>
);
};
function App() {
return <SignupForm />;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
表单验证
对表单输入的内容进行校验。会返回一个errors对象,只有当所有验证都通过时,Submit按钮才会显示未可提交
import React from "react";
import ReactDOM from "react-dom";
import { useFormik } from "formik";
import "./styles.css";
// 入参为表单每一项value的集合
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
if (!values.lastName) {
errors.lastName = 'Required';
} else if (values.lastName.length > 20) {
errors.lastName = 'Must be 20 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
// 最终返回一个errors对象
return errors;
};
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: ""
},
// 放入validate
validate,
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
}
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
// 根据formik.error对象的每一个属性是否有值进行校验信息的输出
{formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
//
onChange={formik.handleChange}
value={formik.values.lastName}
/>
{formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
{formik.errors.email ? <div>{formik.errors.email}</div> : null}
<button type="submit">Submit</button>
</form>
);
};
function App() {
return <SignupForm />;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
增加用户体验的显示方式
如上图,会把所有验证不通过的内容显示出来,我们需要在用户在输入表单的每一项时,输入完这一项立即检查。使用touched和onBlur结合使用
import React from "react";
import ReactDOM from "react-dom";
import { useFormik } from "formik";
import "./styles.css";
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
if (!values.lastName) {
errors.lastName = 'Required';
} else if (values.lastName.length > 20) {
errors.lastName = 'Must be 20 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
return errors;
};
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
validate,
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.firstName}
/>
//使用forkmik.touched来检测该项是否存在错误
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.lastName}
/>
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.touched.email && formik.errors.email ? (
<div>{formik.errors.email}</div>
) : null}
<button type="submit">Submit</button>
</form>
);
};
function App() {
return <SignupForm />;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
第三方验证库Yup的使用
官方强烈建议使用Yup校验库,直接可以使用一些现有的验证
npm install yup --save
import React from "react";
import ReactDOM from "react-dom";
import { useFormik } from "formik";
import "./styles.css";
import * as Yup from 'yup';
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
if (!values.lastName) {
errors.lastName = 'Required';
} else if (values.lastName.length > 20) {
errors.lastName = 'Must be 20 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
return errors;
};
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
// 定义validationSchema
validationSchema: Yup.object({
firstName: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
lastName: Yup.string()
.max(20, 'Must be 20 characters or less')
.required('Required'),
email: Yup.string().email('Invalid email address').required('Required'),
}),
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.firstName}
/>
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.lastName}
/>
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.touched.email && formik.errors.email ? (
<div>{formik.errors.email}</div>
) : null}
<button type="submit">Submit</button>
</form>
);
};
function App() {
return <SignupForm />;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
简化代码内容
使用getFieldProps,使用的范围是input,select,textarea
import React from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
validationSchema: Yup.object({
firstName: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
lastName: Yup.string()
.max(20, 'Must be 20 characters or less')
.required('Required'),
email: Yup.string().email('Invalid email address').required('Required'),
}),
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
type="text"
// 代替 onChange, onBlur, value, checked
{...formik.getFieldProps('firstName')}
/>
{formik.touched.firstName && formik.errors.firstName ? (
<div>{formik.errors.firstName}</div>
) : null}
<label htmlFor="lastName">Last Name</label>
<input id="lastName" type="text" {...formik.getFieldProps('lastName')} />
{formik.touched.lastName && formik.errors.lastName ? (
<div>{formik.errors.lastName}</div>
) : null}
<label htmlFor="email">Email Address</label>
<input id="email" type="email" {...formik.getFieldProps('email')} />
{formik.touched.email && formik.errors.email ? (
<div>{formik.errors.email}</div>
) : null}
<button type="submit">Submit</button>
</form>
);
};