formik介绍

react项目中的表单处理,formik表单处理,表单验证,yup_react项目中的表单处理


​formik的github地址​​​​formik的官网地址​

具体使用

react项目中的表单处理,formik表单处理,表单验证,yup_表单验证_02


react项目中的表单处理,formik表单处理,表单验证,yup_下划线_03

表单验证

react项目中的表单处理,formik表单处理,表单验证,yup_formik表单处理_04


​validate验证线上详细说明​​​​validationSchema线上详细说明​

​A Yup schema 的github地址​​具体操作:

react项目中的表单处理,formik表单处理,表单验证,yup_表单验证_05


完整的登陆代码:

react项目中的表单处理,formik表单处理,表单验证,yup_formik表单处理_06


react项目中的表单处理,formik表单处理,表单验证,yup_react项目中的表单处理_07

import React, { Component } from "react";
import { Flex, WingBlank, WhiteSpace, Toast } from "antd-mobile";

import { Link } from "react-router-dom";
import { withFormik } from "formik";
import * as yup from 'yup';

import API from "../../utils/api";

import NavHeader from "../../components/NavHeader";

import styles from "./index.module.css";
// 验证规则:
const REG_UNAME = /^[a-zA-Z_\d]{5,8}$/
const REG_PWD = /^[a-zA-Z_\d]{5,12}$/
class Login extends Component {
render() {
// 通过props获取高阶组件传递进来的属性
const { values, handleChange, handleSubmit, touched, errors, handleBlur } = this.props;
// 尝试打印一下接收来的高阶组件的值
// console.log(values,handleChange,handleSubmit)
console.log(touched, errors)
return (
<div className={styles.root}>
{/* 顶部导航 */}
<NavHeader className={styles.navHeader}>账号登录</NavHeader>
<WhiteSpace size="xl" />
{/* 登录表单 */}
<WingBlank>
{/* FIXME:两个input框使用的是一个onChange函数,就是因为有了name属性的原因,name属性必须提供并且和values对象的属性一样(受控组件) */}
<form onSubmit={handleSubmit}>
<div className={styles.formItem}>
<input
className={styles.input}
value={values.username}
onChange={handleChange}
onBlur={handleBlur}
name="username"
placeholder="请输入账号"
/>
</div>
{/* 利用的是短路运算符 */}
{errors.username && touched.username && <div className={styles.error}>{errors.username}</div>}
{/* 长度为5到8位,只能出现数字、字母、下划线 */}
<div className={styles.formItem}>
<input
className={styles.input}
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
name="password"
type="password"
placeholder="请输入密码"
/>
</div>
{errors.password && touched.password && <div className={styles.error}>{errors.password}</div>}
{/* 长度为5到12位,只能出现数字、字母、下划线 */}
{/* <div className={styles.error}>账号为必填项</div> */}
<div className={styles.formSubmit}>
<button className={styles.submit} type="submit">
登 录
</button>
</div>
</form>
<Flex className={styles.backHome}>
<Flex.Item>
<Link to="/registe">还没有账号,去注册~</Link>
</Flex.Item>
</Flex>
</WingBlank>
</div>
);
}
}

// 使用withFormik高阶组件包装login组件
Login = withFormik({
// 提供状态
mapPropsToValues: () => ({ username: "", password: "" }),
// validate: values => {
// const errors = {};
// if (!values.name) {
// errors.name = 'Required';
// }
// return errors;
// },
// 表单验证
validationSchema: yup.object().shape({
username: yup.string().required('账号为必填项').matches(REG_UNAME,'长度为5到8位,只能出现数字、字母、下划线'),
password: yup.string().required('密码为必填项').matches(REG_PWD,'长度为5到8位,只能出现数字、字母、下划线'),
}),
// 表单的提交事件
handleSubmit: async (values,{props}) => {
console.log("values", values);
const {
data: { body, description, status },
} = await API.post("/user/login", {
username: values.username,
password: values.password,
});
if (status === 200) {
localStorage.setItem("hkzf_token", body.token);
// 注意:无法在该方法中,通过this来获取到路由信息
// 所以通过第二个对象参数中获取到props来使用props(参数props指的就是被包裹组件的props)
// this.props.history.go(-1);
props.history.go(-1);
} else {
Toast.info(description, 2, null, false);
}
},
})(Login);

export default Login;

简化:

全部都是formik的组件

react项目中的表单处理,formik表单处理,表单验证,yup_yup_08


简化表单处理之后的代码:

import React, { Component } from "react";
import { Flex, WingBlank, WhiteSpace, Toast } from "antd-mobile";

import { Link } from "react-router-dom";
import { withFormik, Form, Field,ErrorMessage } from "formik";
import * as yup from "yup";

import API from "../../utils/api";

import NavHeader from "../../components/NavHeader";

import styles from "./index.module.css";
// 验证规则:
const REG_UNAME = /^[a-zA-Z_\d]{5,8}$/;
const REG_PWD = /^[a-zA-Z_\d]{5,12}$/;
class Login extends Component {
render() {
return (
<div className={styles.root}>
{/* 顶部导航 */}
<NavHeader className={styles.navHeader}>账号登录</NavHeader>
<WhiteSpace size="xl" />
{/* 登录表单 */}
<WingBlank>
{/* FIXME:两个input框使用的是一个onChange函数,就是因为有了name属性的原因,name属性必须提供并且和values对象的属性一样(受控组件) */}
<Form>
<div className={styles.formItem}>
<Field
className={styles.input}
name="username"
placeholder="请输入账号"
></Field>
</div>
<ErrorMessage className={styles.error} name="username" component="div"></ErrorMessage>
<div className={styles.formItem}>
<Field
className={styles.input}
name="password"
type="password"
placeholder="请输入密码"
></Field>
</div>
<ErrorMessage className={styles.error} name="password" component="div"></ErrorMessage>
<div className={styles.formSubmit}>
<button className={styles.submit} type="submit">
登 录
</button>
</div>
</Form>
<Flex className={styles.backHome}>
<Flex.Item>
<Link to="/registe">还没有账号,去注册~</Link>
</Flex.Item>
</Flex>
</WingBlank>
</div>
);
}
}

// 使用withFormik高阶组件包装login组件
Login = withFormik({
// 提供状态
mapPropsToValues: () => ({ username: "", password: "" }),
// validate: values => {
// const errors = {};
// if (!values.name) {
// errors.name = 'Required';
// }
// return errors;
// },
// 表单验证
validationSchema: yup.object().shape({
username: yup
.string()
.required("账号为必填项")
.matches(REG_UNAME, "长度为5到8位,只能出现数字、字母、下划线"),
password: yup
.string()
.required("密码为必填项")
.matches(REG_PWD, "长度为5到8位,只能出现数字、字母、下划线"),
}),
// 表单的提交事件
handleSubmit: async (values, { props }) => {
console.log("values", values);
const {
data: { body, description, status },
} = await API.post("/user/login", {
username: values.username,
password: values.password,
});
if (status === 200) {
localStorage.setItem("hkzf_token", body.token);
// 注意:无法在该方法中,通过this来获取到路由信息
// 所以通过第二个对象参数中获取到props来使用props(参数props指的就是被包裹组件的props)
// this.props.history.go(-1);
props.history.go(-1);
} else {
Toast.info(description, 2, null, false);
}
},
})(Login);

export default Login;