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://:3000 並按 Enter 鍵。

Root Folder

最後,輸入示例費用詳細資訊並點選提交。提交的資料將被收集並在彈出訊息框中顯示。

Root Folders

表單的互動式版本如下所示:

Root Fold
廣告