您好,登錄后才能下訂單哦!
發現Formik是在我學習redux-form過程中從國外一篇博客上偶然發現的,看到作者的高度肯定后我立即轉到github上,正如許多朋友所關注的,Formik的星數達8282,這個數字在github雖然不算很高,但是從基于React技術跨平臺表單開發這個主題角度來看,此數字已經相當可觀了。不自覺地,我對比了redux-form與Formik的幾個數據,如下:
庫 | 開源庫的時間 | 星數 |
---|---|---|
redux-form | 3年以前 | 10210 |
Formik | 1年前 | 8282 |
于是,我得出如下幾個不太肯定的結論(歡迎有興趣的朋友一起討論):
1,redux-form是目前基于React+Redux開發構建表單子項目時主要開源選擇方案;
2,redux-form很可能是目前大多數React程序員心目中高效解決方案的選擇;
3,在github上Formik在未來一年后星數很有可能會超過redux-form項目。
我作出上述猜測主要理由是,經過這段時間我redux-form學習,我發現要深度掌握redux-form實踐應用并靈活地處理各種有關問題,需要花費相當的代價。尤其說明問題的是,在表單體積膨脹和數量急劇增加的情況下,系統的性能有可能受到嚴重的影響。現在我有了react-redux基礎,并理解了redux-form應用原理后,感覺使用Formik開發React表單一下變得異常輕松愉快!
為了節約時間,本系列的幾篇我會首先使用英語方式,再在后面的時間里逐篇翻譯成中文。
至此,你可能會想:“為什么不使用Redux-Form這一方案呢?”對于這個問題,包括我在內的Redux用戶都會自然地提出這個問題。對此,Formik開發者的列出如下三個理由:
**1. React開發專家Dan Abramov認為,表單狀態本質上是短暫的和局部性的,因此通過Redux解決方案(或任何類型的Flux庫)來跟蹤表單狀態是不必要的。
Formik的開發目標是:使用最小的易于使用的API調用創建一個可伸縮的、持久性的表單生成器。當然,還提供另外一些功能供開發者定制使用。
Formik受到Brent Jackson開發的高階組件的啟發 。同時還吸收了Redux-Form庫的命名方案;還有受到React-Motion和React-Router 4的啟發最新引入的render屬性。無論你是否使用過上述這些庫,Formik 都會使你在短短的數分鐘內快速入門。
把Formik添加到你的已有項目中的方式如下:
npm i formik --save
官方網站上提供了一組類似于redux-form官方的示例供初學者學習之用。它們有:
Formik跟蹤表單狀態,然后以props方式把此狀態還有一些可重用的方法和事件處理器(例如 handleChange,handleBlur和handleSubmit暴露給表單組件。其中,handleChange 和handleBlur工作方式完全一樣——都使用name或者id屬性來標記要更新的表單字段。
歸納來看,可以使用如下兩種方式之一來使用Formik:
上述兩種方式完全一樣工作,內部實現原理完全相同。只是各自在使用風格上有所不同而已。請參考如下代碼:
//高階組件方式
import React from 'react';
import { withFormik } from 'formik';
// Our inner form component which receives our form's state and updater methods as props
const InnerForm = ({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{touched.email && errors.email && <div>{errors.email}</div>}
<input
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{touched.password && errors.password && <div>{errors.password}</div>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
);
//使用withFormik HoC包裝表單
const MyForm = withFormik({
// Transform outer props into form values
mapPropsToValues: props => ({ email: '', password: '' }),
// Add a custom validation function (this can be async too!)
validate: (values, props) => {
const errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
},
//表單提交處理器
handleSubmit: (
values,
{
props,
setSubmitting,
setErrors /* setValues, setStatus, and other goodies */,
}
) => {
LoginToMyApp(values).then(
user => {
setSubmitting(false);
// do whatevs...
// props.updateUser(user)
},
errors => {
setSubmitting(false);
// Maybe even transform your API's errors into the same shape as Formik's!
setErrors(transformMyApiErrors(errors));
}
);
},
})(InnerForm);
//然后你可以在任何地方自由使用<MyForm />組件
const Basic = () => (
<div>
<h2>My Form</h2>
<p>This can be anywhere in your application</p>
<MyForm />
</div>
);
export default Basic;
// Render Prop
import React from 'react';
import { Formik } from 'formik';
const Basic = () => (
<div>
<h2>My Form</h2>
<p>This can be anywhere in your application</p>
{/*
The benefit of the render prop approach is that you have full access to React's
state, props, and composition model. Thus there is no need to map outer props
to values...you can just set the initial values, and if they depend on props / state
then--boom--you can directly access to props / state.
The render prop accepts your inner form component, which you can define separately or inline
totally up to you:
- `<Formik render={props => <form>...</form>}>`
- `<Formik component={InnerForm}>`
- `<Formik>{props => <form>...</form>}</Formik>` (identical to as render, just written differently)
*/}
<Formik
initialValues={{
email: '',
password: '',
}}
validate={values => {
// same as above, but feel free to move this into a class method now.
let errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(
values,
{ setSubmitting, setErrors /* setValues and other goodies */ }
) => {
LoginToMyApp(values).then(
user => {
setSubmitting(false);
// do whatevs...
// props.updateUser(user)
},
errors => {
setSubmitting(false);
// Maybe transform your API's errors into the same shape as Formik's
setErrors(transformMyApiErrors(errors));
}
);
}}
render={({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{touched.email && errors.email && <div>{errors.email}</div>}
<input
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{touched.password && errors.password && <div>{errors.password}</div>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
)}
/>
</div>
);
export default Basic;
正你從上面觀察到的,表單的校驗邏輯完全由開發者自己實現。你可以心情使用第三方庫來編寫你自己的定制校驗器。從官方網站上了解到,示例中大量使用Yup庫來實現對象的格式校驗。它提供了一種十分類似于Joi / React PropTypes的API,只不過在瀏覽器中尺寸十分小巧,且對運行時應用來說已經足夠快。在此建議同學們也積極使用Yup。并且在Formik中也針對Yup提供了一種特別的配置選項/屬性稱作validationSchema,它能夠把Yup的校驗錯誤自動轉換成一種很小的對象(對象中也提供了values和touched等鍵支持)。使用npm把Yup安裝到你的項目中的方式如下:
npm install yup --save
1.https://github.com/jaredpalmer/formik
2.http://www.lizhe.name/node/252
3.https://keyholesoftware.com/2017/10/23/the-joy-of-forms-with-react-and-formik/
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。