React_Formik

React 表單 Formik

表單 – React

Controlled Component

一個完整的、包含驗證、可追蹤拜訪欄位並能處理提交表單等功能的解決方案,Formik 是一個很熱門的選擇。然而,它是在與 controlled component 和維持 state 相同的原則上所建立的,所以別忘了學習它。

[[React_表單_Formik]]

Uncontrolled Component

表單的資料是由 DOM 本身所處理的。使用 ref 來從 DOM 取得表單的資料,而不是為了每個 state 的更新寫 event handler。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.input = React.createRef();
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.current.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={this.input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

有的時候使用 uncontrolled component 時更容易整合 React 和非 React 的程式碼。如果你想有個又快又髒的方法,它也可以減少一些程式碼。否則,通常應使用 controlled component。

在 React 裡,<input type="file" /> 永遠都是 uncontrolled component,因為它的值只能被使用者設定,而無法由程式碼來設定。

Formik

文件提到了 react context 於是又去學了 [[React 主要概念#context API]]

Tutorial | Formik | Formik

useFormik

We pass our form’s initialValues and a submission function (onSubmit) to the useFormik() hook. The hook then returns to us a goodie bag of form state and helper methods in a variable we call formik. For now, the only helper methods we care about are as follows:

  • handleSubmit: A submission handler
  • handleChange: A change handler to pass to each <input>, <select>, or <textarea>
  • values: Our form’s current values

change handler function 的原理

If you’re familiar with building forms with plain React, you can think of Formik’s handleChange as working like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

const [values, setValues] = React.useState({});

 const handleChange = event => {
   setValues(prevValues => ({
     ...prevValues,
     // we use the name to tell Formik which key of `values` to update
     [event.target.name]: event.target.value
   });
 }

Validation

Formik keeps track of not only your form’s values, but also its validation and error messages. To add validation with JS, let’s specify a custom validation function and pass it as validate to the useFormik() hook. If an error exists, this custom validation function should produce an error object with a matching shape to our values/initialValues.

Visited fields

we only want to show a field’s error message after our user is done typing in that field.

Like errors and values, Formik keeps track of which fields have been visited. It stores this information in an object called touched that also mirrors the shape of values/initialValues. The keys of touched are the field names, and the values of touched are booleans true/false.

To take advantage of touched, we pass formik.handleBlur to each input’s onBlur prop. This function works similarly to formik.handleChange in that it uses the name attribute to figure out which field to update.

Schema Validation with Yup

yarn add yup

Formik has a special configuration prop for Yup called validationSchema which will automatically transform Yup’s validation errors messages into a pretty object whose keys match values/initialValues/touched

改傳入 validationSchema 給 useFormik 就好了

讓程式碼更簡潔

getFieldProps()

onChange -> handleChange, onBlur -> handleBlur, and so on. However, to save you time, useFormik() returns a helper method called formik.getFieldProps() to make it faster to wire up inputs. Given some field-level info, it returns to you the exact group of onChange, onBlur, value, checked for a given field. You can then spread that on an input, select, or textarea.

1
2
3
4
5
6
7
8
<input
	id="firstName"
	name="firstName"
	type="text"
	onChange={formik.handleChange}
	onBlur={formik.handleBlur}
	value={formik.values.firstName}
/>

變成

1
2
3
4
5
6
7
<input 

	id="firstName" 
	type="text" 
	{...formik.getFieldProps("firstName")} 

/>

Leveraging React Context

  • 從這邊順便再去複習 react context [[React context API]]
  • 可以再去細看, render props 的概念 [[React render props]]

<Formik> component 實作原理

  • 可以再去細看,增加 react context 如何應用的知識 Tutorial | Formik | Formik

  • The <Formik> component accepts a function as its children (a.k.a. a render prop). Its argument is the exact same object returned by useFormik() (in fact, <Formik> calls useFormik() internally!).

講半天 <Formik> Field, Form, ErrorMessage component ,怎麼用?

Formik

There are 2 ways to render things with <Formik />

  • <Formik component>
  • <Formik children>
Field

The <Field> component by default will render an <input> component that, given a name prop, will implicitly grab the respective onChange, onBlur, value props and pass them to the element as well as any props you pass to it.

However, since not everything is an input, <Field> also accepts a few other props to let you render whatever you want.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

// <input className="form-input" placeHolder="Jane"  />
 <Field name="firstName" className="form-input" placeholder="Jane" />
 
 // <textarea className="form-textarea"/></textarea>
 <Field name="message" as="textarea" className="form-textarea" />
 
 // <select className="my-select"/>
 <Field name="colors" as="select" className="my-select">
   <option value="red">Red</option>
   <option value="green">Green</option>
   <option value="blue">Blue</option>
 </Field>
Form
ErrorMessage

| Formik | FormikuseField() | Formik | Formik

使用 useField

useField() | Formik | Formik

useField is a custom React hook that will automagically help you hook up inputs to Formik. You can and should use it to build your own custom input primitives.

教學影片

Formik 2 Tutorial | React Forms - YouTube

最後更新 Mar 30, 2022 15:59 +0800