formik介绍

在这里插入图片描述
formik的github地址
formik的官网地址

具体使用

在这里插入图片描述
在这里插入图片描述

表单验证

在这里插入图片描述
validate验证线上详细说明
validationSchema线上详细说明
A Yup schema 的github地址

具体操作:
在这里插入图片描述
完整的登陆代码:
在这里插入图片描述
在这里插入图片描述

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的组件
在这里插入图片描述
简化表单处理之后的代码:

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;

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐