Formik Material UI React Form 使用 Formik、Material-UI 和 Yup。

2025-05-27

Formik Material UI React Form 使用 Formik、Material-UI 和 Yup。

介绍

有时,在 React 中管理表单可能会很麻烦。如果您决定使用像 redux-form 这样的库,它们会带来显著的性能开销,而您正在构建的应用程序中可能无法承受这些开销。Formik 可以帮您解决这个问题。它体积小巧,打包后大小为 12 kB,而 redux-form 打包后(最小化后 gzip 压缩)大小为 22.5 kB。最棒的是,Formik 可以帮助处理繁琐的表单处理任务,

  • 处理表单状态
  • 处理表单验证和错误
  • 处理表单提交

您可以查看文档以获取有关Formik库的更多信息

Formik 还与 material-ui 无缝集成;它是一个实现 Google 材料设计的反应库,提供开箱即用的输入、按钮、标签等组件。

您还可以查看他们的文档以获取有关Material-Ui 的更多信息

最后,还有 Yup。Yup 是什么?它是一个 JavaScript 对象模式验证器和对象解析器。在这里,Yup 只是帮助处理验证。这并不意味着你不能为 Formik 编写自定义验证器,只是我发现 Yup 的使用体验很好,它提高了我的代码的可读性。

有关 Yup 的更多信息,请参阅文档Yup

本文将解释如何使用 Formik、Yup 和 Material-UI 构建表单并处理表单验证。

以下是我们将在本指南中做的事情的简要概述:

  • 使用 create-react-app 创建一个 React 应用程序。
  • 使用 Material-UI 和 Formik 创建一个简单的表单。
  • 使用 Yup 编写验证规则/验证模式。
  • 将 Yup 与 Formik 一起使用。

本教程假设您已了解 React。

这里有一个我们要构建的表单的代码沙盒演示:
Formik 演示应用程序

安装:

Create-react-app formik-form-demo

运行此程序后,我们的项目结构应如下所示:

文件结构

现在打开文件夹App.js中的文件,然后删除具有 className 的src父级的内容。div

App.js

在你的终端运行

Yarn add or npm install formik yup @material-ui/core

Enter fullscreen mode Exit fullscreen mode

此命令将 formik、Yup 和 material-UI 添加到我们的依赖项中。现在我们的依赖项已经安装完毕,请在文件夹InputForm中创建一个名为 的新文件夹,src然后在文件夹中创建index.jsform.js文件InputForm

您的 src 文件夹现在应该是这样的:

src 现在

form.js文件将包含演示文稿,而 则index.js包含大部分逻辑。
目前您的应用程序应该显示一个空白页,所以现在我们只需显示表单即可。

在您的form.js文件中添加以下代码

import React from "react";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";

export const Form = (props) => {
  return (
   <form onSubmit={() => {}}>
     <TextField
       id="name"
       name="name"
       label="Name"
       fullWidth

     />
     <TextField
       id="email"
       name="email"
       label="Email"
       fullWidth
     />
     <TextField
       id="password"
       name="password"
       label="Password"
       fullWidth
       type="password"
     />
     <TextField
       id="confirmPassword"
       name="confirmPassword"
       label="Confirm Password"
       fullWidth
       type="password"
     />
     <Button
       type="submit"
       fullWidth
       variant="raised"
       color="primary"
     >
       Submit
     </Button>
   </form>
 );
};


Enter fullscreen mode Exit fullscreen mode

我们在这里所做的是创建一个包含四个字段(姓名、电子邮件、密码和确认密码)和一个带有material-UI的按钮的简单表单。

index.js在文件夹中的文件InputForm添加以下代码:


import React, { Component } from "react";
import { Formik } from "formik";
import withStyles from "@material-ui/core/styles/withStyles";
import { Form } from "./form";
import Paper from "@material-ui/core/Paper";

const styles = theme => ({
 paper: {
   marginTop: theme.spacing.unit * 8,
   display: "flex",
   flexDirection: "column",
   alignItems: "center",
   padding: `${theme.spacing.unit * 5}px ${theme.spacing.unit * 5}px ${theme
     .spacing.unit * 5}px`
 },
 container: {
   maxWidth: "200px"
 }
});

class InputForm extends Component {
 constructor(props) {
   super(props);
   this.state = {};
 }

 render() {
   const classes = this.props;
   return (
     <React.Fragment>
          <div className={classes.container}>
         <Paper elevation={1} className={classes.paper}>
           <h1>Form</h1>
           <Formik
             render={props => <Form {...props} />}
           />
         </Paper>
       </div>
     </React.Fragment>
   );
 }
}

export default withStyles(styles)(InputForm);




Enter fullscreen mode Exit fullscreen mode

这里我们创建了一个名为 的类组件InputForm。在顶部,我们导入了刚刚创建的表单组件。然后将其作为 传递render prop给该Formik组件。

使用 Formik 渲染事物有三种方式

  • <Formik component />
  • <Formik render />
  • <Formik children />

render props我们在上面使用了。所有三个渲染方法都会传递一些 props,包括:

  • 错误
  • handleChange
  • 处理
  • 是否有效
  • 感动
  • 设置FieldTouched

还有一些 props 传递给你的组件,请查看文档以了解所有相关内容Formik Docs

接下来,转到文件夹App.js中的文件src,导入InputForm组件,然后将其添加为的子项div。现在App.js,表单应该被渲染了。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import InputForm from './InputForm'

class App extends Component {
 render() {
   return (
     <div className="App">
       <InputForm/>
     </div>
   );
 }
}

export default App;

Enter fullscreen mode Exit fullscreen mode

初始形式

现在表单已经渲染完毕,让我们开始进行表单验证。这时就需要用到 Yup 了。Yup 提供了一些函数,帮助我们编写直观的验证规则。
首先,我们将 Yup 导入到文件夹Index.js中的文件中InputForm,然后使用它的 API 来编写验证规则。

导入语句
import * as Yup from "yup"

注意:将库的所有函数/API 导入到代码库中并不是一个好的做法。

现在将以下代码添加到文件夹Index.js中的文件中InputForm,这是我们的验证规则或验证方案。


const validationSchema = Yup.object({
name: Yup.string("Enter a name")
.required("Name is required"),
email: Yup.string("Enter your email")
.email("Enter a valid email")
.required("Email is required"),
password: Yup.string("")
.min(8, "Password must contain at least 8 characters")
.required("Enter your password"),
confirmPassword: Yup.string("Enter your password")
.required("Confirm your password")
.oneOf([Yup.ref("password")], "Password does not match")


Enter fullscreen mode Exit fullscreen mode

我不知道你是怎么想的,但乍一看,这看起来非常直观。Yup 提供了几个 API,使对象验证变得简单。下面列出了其中一些。

蜜蜂

Yup.object():用于定义对象的键以及这些键对应的模式。在本例中,它用于定义我们要验证的字段(名称、电子邮件、密码、确认密码),并定义这些字段的验证规则。

Yup.string():定义一个字符串模式。它指定字段应为字符串,并接受一个可选参数,用于设置错误消息。我们定义的所有四个字段都是字符串。此外,我们可以链接函数或方法,以便每个字段可以有多个验证规则。

Yup.required():指定该字段为必填项,且不能为空。它还接受一个可选参数来定义错误消息。

Yup.email():定义电子邮件模式并采用可选参数。

Yup.min():设置值的最小长度。它接受两个参数:长度和错误消息。

Yup.ref():它创建对另一个同级字段或同级后代字段的引用。它接受一个强制参数,即我们引用的字段。

Yup.oneOf():将一组值列入白名单。它接受一个包含白名单值的数组和一个用于设置错误消息的可选参数。

查看文档以获取 API 的完整列表。

现在我们已经定义了验证模式/规则,我们如何将其集成到我们的应用程序中?

还记得我之前说过 Yup 与 Formik 无缝集成吗?Formik 为 Yup 提供了一个特殊的 prop,名为 ,validationSchema它会自动将 Yup 的验证错误转换为一个美观的对象。所以我们将验证规则传递给这个validationSchemaprop。Formik 还允许你使用这个 prop 为字段设置初始值initialValues

因此,当我们将and prop 添加到 Formik 组件时,我们组件的渲染函数InputForm应该是这样的。validationSchemainitialValues


render() {
  const classes = this.props;
  const values = { name: "", email: "", confirmPassword: "", password: "" };
  return (
<React.Fragment>
    <div className={classes.container}>
        <Paper elevation={1} className={classes.paper}>
        <h1>Form</h1>
        <Formik
            render={props => <Form {...props} />}
            initialValues={values}
            validationSchema={validationSchema}
        />
        </Paper>
    </div>
</React.Fragment>
);
}

Enter fullscreen mode Exit fullscreen mode

我们已经定义了验证规则和初始值,现在让我们使用传递给 Form 组件的 props 来处理验证输入。

在文件夹中的 Form 组件中InputForm,我们解构 props 并创建一个处理输入变化的更改函数

const {
values: { name, email, password, confirmPassword },
errors,
touched,
handleSubmit,
handleChange,
isValid,
setFieldTouched
} = props;


const change = (name, e) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
};


Enter fullscreen mode Exit fullscreen mode

有一些 props 传递给了 Form 组件,Formik但在本演示中我不会全部用到它们。
使用的 props 如下:

  • values :包含表单字段初始值的对象。

  • 错误:包含字段错误消息的对象。

  • touched :包含已被触摸/访问过的字段的对象,已被触摸的字段设置为 true,否则设置为 false。

  • handleChange :通用输入处理程序,它将更新 values[key] ,其中 key 是触发事件的输入框的 name 属性。如果 name 属性不存在,handleChange 将查找输入框的 id 属性。

  • isValid:如果没有错误,即错误对象中没有错误,则返回 true。

  • setFieldTouched: 是一个用于设置字段触摸状态的函数。第一个参数是字段名称,第二个参数是要设置触摸状态的值,如果为 true,则为真;最后一个参数是一个布尔值,用于阻止验证。

现在让我们对 Form 组件进行一些修改,以便在出现错误时能够看到错误消息。Material
-UITextField组件提供了两个 props,可以帮助我们以优雅的方式显示错误消息,这两个 props 分别是helperTexterror用于显示错误。

当我们将这些道具添加到我们的组件时,表单组件应该是这样的TextField


export const Form = props => {
 const {
   values: { name, email, password, confirmPassword },
   errors,
   touched,
   handleChange,
   isValid,
   setFieldTouched
 } = props;

 const change = (name, e) => {
   e.persist();
   handleChange(e);
   setFieldTouched(name, true, false);
 };
 return (
   <form
     onSubmit={() => {
       alert("submitted");
     }}
   >
     <TextField
       id="name"
       name="name"
       helperText={touched.name ? errors.name : ""}
       error={touched.name && Boolean(errors.name)}
       label="Name"
       value={name}
       onChange={change.bind(null, "name")}
       fullWidth

     />
     <TextField
       id="email"
       name="email"
       helperText={touched.email ? errors.email : ""}
       error={touched.email && Boolean(errors.email)}
       label="Email"
       fullWidth
       value={email}
       onChange={change.bind(null, "email")}

     />
     <TextField
       id="password"
       name="password"
       helperText={touched.password ? errors.password : ""}
       error={touched.password && Boolean(errors.password)}
       label="Password"
       fullWidth
       type="password"
       value={password}
       onChange={change.bind(null, "password")}

     />
     <TextField
       id="confirmPassword"
       name="confirmPassword"
       helperText={touched.confirmPassword ? errors.confirmPassword : ""}
       error={touched.confirmPassword && Boolean(errors.confirmPassword)}
       label="Confirm Password"
       fullWidth
       type="password"
       value={confirmPassword}
       onChange={change.bind(null, "confirmPassword")}

     />
     <Button
       type="submit"
       fullWidth
       variant="raised"
       color="primary"
       disabled={!isValid}
     >
       Submit
     </Button>
   </form>
 );
};



Enter fullscreen mode Exit fullscreen mode

Textfield您应该注意到,我向组件添加了三个 props ,分别helperText是 、erroronChange
onChange设置为我们上面编写的用于处理输入字段更改的 change 函数。
prophelperText设置为三元运算符(If 语句),用于指示如果触摸了该字段,则将helperTextprop 设置为该字段的错误消息,否则将其设置为空字符串。errorprop 设置为布尔值,表示验证错误。

最后,Button组件有一个名为的 prop disabled,用于禁用按钮,我们将其设置为不禁用,!isValid这样如果错误对象中出现任何错误,按钮就会保持禁用状态,我的意思是我们不想提交无效值。

最终工作形式

使用 Formik、Material-UI 和 Yup 创建表单非常棒。

这是我的第一篇技术文章/帖子,因此我愿意接受任何有助于提高我写作水平的建议。

如果您有任何问题或建议,请在下面发表评论。

特别感谢我的朋友YJTheRuler编辑这篇文章,他为@radronline撰写有关非洲音乐和非洲文化的文章。

文章来源:https://dev.to/finallynero/react-form-using-formik-material-ui-and-yup-2e8h
PREV
在 React 中使用 WebSockets
NEXT
React-Router v5.1 中引入的 Hooks