ReactJS - Formik



Formik 是一个第三方 React 表单库。它提供基本的表单编程和验证功能。它基于受控组件,极大地减少了表单编程所需的时间。

表单编程的本质需要维护状态。因为,当用户与表单交互时,输入字段信息会发生变化。但正如我们之前学到的,React 库本身并不存储或维护任何状态信息,组件必须使用状态管理 API 来管理状态。考虑到这一点,React 提供了两种类型的组件来支持表单编程。

使用 Formik 的费用表单

在本章中,让我们使用 Formik 库重新创建费用表单。

步骤 1 - 首先,使用 Create React AppRollup 捆绑器创建一个新的 React 应用,名为 react-formik-app,方法是按照 创建 React 应用 一章中的说明进行操作。

步骤 2 - 安装 Formik 库。

cd /go/to/workspace npm install formik --save

步骤 3 - 在您喜欢的编辑器中打开该应用。

在应用的根目录下创建 src 文件夹。

在 src 文件夹下创建 components 文件夹。

步骤 4 - 在 src 文件夹下创建一个文件,名为 ExpenseForm.css,用于为组件设置样式。

input[type=text], input[type=number], input[type=date], select {
   width: 100%;
   padding: 12px 20px;
   margin: 8px 0;
   display: inline-block;
   border: 1px solid #ccc;
   border-radius: 4px;
   box-sizing: border-box;
}
input[type=submit] {
   width: 100%;
   background-color: #4CAF50;
   color: white;
   padding: 14px 20px;
   margin: 8px 0;
   border: none;
   border-radius: 4px;
   cursor: pointer;
}
input[type=submit]:hover {
   background-color: #45a049;
}
input:focus {
   border: 1px solid #d9d5e0;
}
#expenseForm div {
   border-radius: 5px;
   background-color: #f2f2f2;
   padding: 20px;
}
#expenseForm span {
   color: red;
}

步骤 5 - 在 src/components 文件夹下创建另一个文件,名为 ExpenseForm.js,并开始编辑。

导入 ReactFormik 库。

import React from 'react'; 
import { Formik } from 'formik';

接下来,导入 ExpenseForm.css 文件。

import './ExpenseForm.css'

接下来,创建 ExpenseForm 类。

class ExpenseForm extends React.Component {        
   constructor(props) { 
      super(props); 
   } 
}

在构造函数中设置费用项目的初始值。

this.initialValues = { name: '', amount: '', date: '', category: '' }

接下来,创建一个验证方法。Formik 将发送用户输入的当前值。

validate = (values) => {
   const errors = {};
   if (!values.name) {
      errors.name = 'Required';
   }
   if (!values.amount) {
      errors.amount = 'Required';
   }
   if (!values.date) {
      errors.date = 'Required';
   }
   if (!values.category) {
      errors.category = 'Required';
   }
   return errors;
}

创建一个提交表单的方法。Formik 将发送用户输入的当前值。

handleSubmit = (values, setSubmitting) => {
   setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
   }, 400);
}

创建 render() 方法。使用 Formik 提供的 handleChange、handleBlur 和 handleSubmit 方法作为输入元素的事件处理程序。

render() {
   return (
      <div id="expenseForm">
         <Formik
            initialValues={this.initialValues}
            validate={values => this.validate(values)}
            onSubmit={(values, { setSubmitting }) => this.handleSubmit(values, setSubmitting)} >{
               ({
                  values,
                  errors,
                  touched,
                  handleChange,
                  handleBlur,
                  handleSubmit,
                  isSubmitting,
                  /* and other goodies */
               }) 
               => (
                  <form onSubmit={handleSubmit}>
                     <label for="name">Title <span>{errors.name && touched.name && errors.name}</span></label>
                     <input type="text" id="name" name="name" placeholder="Enter expense title"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.name} />

                     <label for="amount">Amount <span>{errors.amount && touched.amount && errors.amount}</span></label>
                     <input type="number" id="amount" name="amount" placeholder="Enter expense amount"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.amount} />

                     <label for="date">Spend Date <span>{errors.date && touched.date && errors.date}</span></label>
                     <input type="date" id="date" name="date" placeholder="Enter date"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.date} />

                     <label for="category">Category <span>{errors.category && touched.category && errors.category}</span></label>
                     <select id="category" name="category"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.category}>
                        <option value="">Select</option>
                        <option value="Food">Food</option>
                        <option value="Entertainment">Entertainment</option>
                        <option value="Academic">Academic</option>
                     </select>

                     <input type="submit" value="Submit" disabled={isSubmitting} />
                  </form>
               )
            }
         </Formik>
      </div>
   )
}

最后,导出组件。

export default ExpenseForm

下面给出了 ExpenseForm 组件的完整代码。

import React from 'react';
import './ExpenseForm.css'
import { Formik } from 'formik';

class ExpenseFormik extends React.Component {
   constructor(props) {
      super(props);

      this.initialValues = { name: '', amount: '', date: '', category: '' }
   }
   validate = (values) => {
      const errors = {};
      if (!values.name) {
         errors.name = 'Required';
      }
      if (!values.amount) {
         errors.amount = 'Required';
      }
      if (!values.date) {
         errors.date = 'Required';
      }
      if (!values.category) {
         errors.category = 'Required';
      }
      return errors;
   }
   handleSubmit = (values, setSubmitting) => {
      setTimeout(() => {
         alert(JSON.stringify(values, null, 2));
         setSubmitting(false);
      }, 400);
   }
   render() {
      return (
         <div id="expenseForm">
            <Formik
               initialValues={this.initialValues}
               validate={values => this.validate(values)}
               onSubmit={(values, { setSubmitting }) => this.handleSubmit(values, setSubmitting)} > 
               {
                  ({
                     values,
                     errors,
                     touched,
                     handleChange,
                     handleBlur,
                     handleSubmit,
                     isSubmitting,
                     /* and other goodies */
                  }) => 
                  (
                     <form onSubmit={handleSubmit}>
                        <label for="name">Title <span>{errors.name && touched.name && errors.name}</span></label>
                        <input type="text" id="name" name="name" placeholder="Enter expense title"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.name} />

                        <label for="amount">Amount <span>{errors.amount && touched.amount && errors.amount}</span></label>
                        <input type="number" id="amount" name="amount" placeholder="Enter expense amount"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.amount} />

                        <label for="date">Spend Date <span>{errors.date && touched.date && errors.date}</span></label>
                        <input type="date" id="date" name="date" placeholder="Enter date"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.date} />

                        <label for="category">Category <span>{errors.category && touched.category && errors.category}</span></label>
                        <select id="category" name="category"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.category}>
                           <option value="">Select</option>
                           <option value="Food">Food</option>
                           <option value="Entertainment">Entertainment</option>
                           <option value="Academic">Academic</option>
                        </select>

                        <input type="submit" value="Submit" disabled={isSubmitting} />
                     </form>
                  )
               }
            </Formik>
         </div>
      )
   }
}
export default ExpenseForm;

index.js

在 src 文件夹下创建一个文件,名为 index.js,并使用 ExpenseForm 组件。

import React from 'react';
import ReactDOM from 'react-dom';
import ExpenseForm from './components/ExpenseForm'

ReactDOM.render(
   <React.StrictMode>
      <ExpenseForm />
   </React.StrictMode>,
   document.getElementById('root')
);

index.html

最后,在根文件夹下创建一个 public 文件夹,并在其中创建 index.html 文件。

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React App</title>
   </head>
   <body>
      <div id="root"></div>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

使用 npm 命令启动应用。

npm start

打开浏览器,在地址栏中输入 https://127.0.0.1:3000 并按 Enter 键。

Root Folder

最后,输入示例费用详细信息并点击提交。提交的数据将被收集并在弹出消息框中显示。

Root Folders

表单的交互式版本如下所示:

Root Fold
广告