日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Formik轻松开发更高质量的React表单(二)使用指南

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Formik轻松开发更高质量的React表单(二)使用指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個基本的例子

設想你要開發一個可以編輯用戶數據的表單。不過,你的用戶API端使用了具有類似下面的嵌套對象表達:

{id: string,email: string,social: {facebook: string,twitter: string,// ...} }

最后,我們想使開發的對話框表單能夠接收下面幾個屬性(props):user,updateUser和onClose(顯然,user是一個對象,updateUser和onClose卻都是兩個方法)。

// User.js import React from 'react'; import Dialog from 'MySuperDialog'; import { Formik } from 'formik';const EditUserDialog = ({ user, updateUser, onClose }) => {return (<Dialog onClose={onClose}><h1>Edit User</h1><FormikinitialValues={user /** { email, social } */}onSubmit={(values, actions) => {CallMyApi(user.id, values).then(updatedUser => {actions.setSubmitting(false);updateUser(updatedUser), onClose();},error => {actions.setSubmitting(false);actions.setErrors(transformMyAPIErrorToAnObject(error));});}}render={({values,errors,touched,handleBlur,handleChange,handleSubmit,isSubmitting,}) => (<form onSubmit={handleSubmit}><inputtype="email"name="email"onChange={handleChange}onBlur={handleBlur}value={values.email}/>{errors.email && touched.email && <div>{errors.email}</div>}<inputtype="text"name="social.facebook"onChange={handleChange}onBlur={handleBlur}value={values.social.facebook}/>{errors.social &&errors.social.facebook &&touched.facebook && <div>{errors.social.facebook}</div>}<inputtype="text"name="social.twitter"onChange={handleChange}onBlur={handleBlur}value={values.social.twitter}/>{errors.social &&errors.social.twitter &&touched.twitter && <div>{errors.social.twitter}</div>}<button type="submit" disabled={isSubmitting}>Submit</button></form>)}/></Dialog>); };

簡化編碼

為了簡化表單組件的編碼,Formik還提供了兩個幫助API:


  • <Field>

  • <Form />


于是,下面的代碼與前面一致,只是使用<Form />和<Field />這兩個API進行了改寫:

// EditUserDialog.js import React from 'react'; import Dialog from 'MySuperDialog'; import { Formik, Field, Form } from 'formik';const EditUserDialog = ({ user, updateUser, onClose }) => {return (<Dialog onClose={onClose}><h1>Edit User</h1><FormikinitialValues={user /** { email, social } */}onSubmit={(values, actions) => {CallMyApi(user.id, values).then(updatedUser => {actions.setSubmitting(false);updateUser(updatedUser), onClose();},error => {actions.setSubmitting(false);actions.setErrors(transformMyAPIErrorToAnObject(error));});}}render={({ errors, touched, isSubmitting }) => (<Form><Field type="email" name="email" />{errors.email && touched.social.email && <div>{errors.email}</div>}<Field type="text" name="social.facebook" />{errors.social.facebook &&touched.social.facebook && <div>{errors.social.facebook}</div>}<Field type="text" name="social.twitter" />{errors.social.twitter &&touched.social.twitter && <div>{errors.social.twitter}</div>}<button type="submit" disabled={isSubmitting}>Submit</button></Form>)}/></Dialog>); };

React Native開發問題


Formik與React Native 和React Native Web開發完全兼容。然而,由于ReactDOM和React Native表單處理與文本輸入方式的不同,有兩個區別值得注意。本文將介紹這個問題并推薦更佳使用方式。

在進一步討論前,先來最簡要地概括一下如何在React Native中使用Formik。下面的輪廓代碼展示了兩者的關鍵區別:

// Formik +React Native示例 import React from 'react'; import { Button, TextInput, View } from 'react-native'; import { withFormik } from 'formik';const enhancer = withFormik({/*...*/ });const MyReactNativeForm = props => (<View><TextInputonChangeText={props.handleChange('email')}onBlur={props.handleBlur('email')}value={props.values.email}/><Button onPress={props.handleSubmit} title="Submit" /></View> );export default enhancer(MyReactNativeForm);

從上面代碼中,你會明顯注意到在React Native 和React DOM開發中使用Formik存在如下不同:


(1)Formik的props.handleSubmit被傳遞給一個<Button onPress={...} />,而不是HTML <form onSubmit={...} /> 組件(因為在React Native中沒有<form />元素)。

(2)<TextInput />使用Formik的props.handleChange(fieldName)和handleBlur(fieldName),而不是直接把回調函數賦值給props,因為我們必須從某處得到fieldName,而在ReactNative中我們無法你在Web中一樣自動獲取它(使用input的name屬性)。作為可選方案,你還可以使用 setFieldValue(fieldName, value) 和setTouched(fieldName, bool) 這兩個函數。


避免在render中創建新函數

如果因某種原因你想在每一個render中避免創建新函數,那么我建議你把React Native的 <TextInput /> 當作它是一個第三方提供的定制輸入元素:


  • 編寫你自己的針對定制輸入元素的類包裝器;
  • 傳遞定制組件的props.setFieldValue,而不是傳遞props.handleChange;
  • 使用一個定制的change函數回調,它將調用你傳遞給setFieldValue的任何內容。

請參考下面的代碼:

// FormikReactNativeTextInput.js import * as React from 'react'; import { TextInput } from 'react-native';export default class FormikReactNativeTextInput extends React.Component {handleChange = (value: string) => {// remember that onChangeText will be Formik's setFieldValuethis.props.onChangeText(this.props.name, value);};render() {// we want to pass through all the props except for onChangeTextconst { onChangeText, ...otherProps } = this.props;return (<TextInputonChangeText={this.handleChange}{...otherProps} // IRL, you should be more explicit when using TS/>);} }

然后,你可以像下面這樣使用這個定制輸入組件:

// MyReactNativeForm.js import { View, Button } from 'react-native'; import TextInput from './FormikReactNativeTextInput'; import { Formik } from 'formik';const MyReactNativeForm = props => (<View><FormikonSubmit={(values, actions) => {setTimeout(() => {console.log(JSON.stringify(values, null, 2));actions.setSubmitting(false);}, 1000);}}render={props => (<View><TextInputname="email"onChangeText={props.setFieldValue}value={props.values.email}/><Button title="submit" onPress={props.handleSubmit} /></View>)}/></View> );export default MyReactNativeForm;

使用TypeScript開發Formik表單

(一)TypeScript類型

Formik是使用TypeScript寫的,Formik中的類型十分類似于React Router 4中的<Route>。

Render props (<Formik /> and <Field />) import * as React from 'react'; import { Formik, FormikProps, Form, Field, FieldProps } from 'formik';interface MyFormValues {firstName: string; }export const MyApp: React.SFC<{} /* whatever */> = () => {return (<div><h1>My Example</h1><FormikinitialValues={{ firstName: '' }}onSubmit={(values: MyFormValues) => alert(JSON.stringify(values))}render={(formikBag: FormikProps<MyFormValues>) => (<Form><Fieldname="firstName"render={({ field, form }: FieldProps<MyFormValues>) => (<div><input type="text" {...field} placeholder="First Name" />{form.touched.firstName &&form.errors.firstName &&form.errors.firstName}</div>)}/></Form>)}/></div>); };

(二)使用withFormik()

import React from 'react'; import * as Yup from 'yup'; import { withFormik, FormikProps, FormikErrors, Form, Field } from 'formik';// Shape of form values interface FormValues {email: string;password: string; }interface OtherProps {message: string; }

順便提醒一下,你可以使用InjectedFormikProps<OtherProps, FormValues>來代替下面的實現方式。本質上,它們是相同的,只不過InjectedFormikProps是當Formik僅輸出一個HOC(高階組件)時的代替而已。而且,這個方法靈活性差一些,因為它需要對所有屬性(props)進行包裝。

const InnerForm = (props: OtherProps & FormikProps<FormValues>) => {const { touched, errors, isSubmitting, message } = props;return (<Form><h1>{message}</h1><Field type="email" name="email" />{touched.email && errors.email && <div>{errors.email}</div>}<Field type="password" name="password" />{touched.password && errors.password && <div>{errors.password}</div>}<button type="submit" disabled={isSubmitting}>Submit</button></Form>); };//MyForm接收的props的類型 interface MyFormProps {initialEmail?: string;message: string; // if this passed all the way through you might do this or make a union type }//使用withFormik高階組件包裝你的表單 const MyForm = withFormik<MyFormProps, FormValues>({// Transform outer props into form valuesmapPropsToValues: props => {return {email: props.initialEmail || '',password: '',};},//添加定制的校驗函數(也有可能是異步的)validate: (values: FormValues) => {let errors: FormikErrors = {};if (!values.email) {errors.email = 'Required';} else if (!isValidEmail(values.email)) {errors.email = 'Invalid email address';}return errors;},handleSubmit: values => {// do submitting things}, })(InnerForm);// 你可以在任何地方使用<MyForm /> const Basic = () => (<div><h1>My App</h1><p>This can be anywhere in your application</p><MyForm message="Sign up" /></div> );export default Basic;

Formik表單提交原理


要在Formik中提交表單,你需要以某種方式觸發 handleSubmit(e) 或者submitForm屬性調用(在Formik中這兩個方法都是以屬性的方式提供的)。 當調用其中一個方法時,Formik每次都會執行下面的偽代碼:

(一)預提交
(1)修改所有字段
(2)把isSubmitting 設置為true
(3)submitCount + 1
(二)校驗
(1)把isValidating設置為true
(2)異步運行所有字段級的校驗和validationSchema,并深度合并執行結果
(3)判斷是否存在錯誤:
如果存在錯誤:取消提交,把isValidating設置為false,設置錯誤信息,并把isSubmitting設置為false
如果不存在錯誤:Set isValidating to false, proceed to "Submission"
(三)提交
最后繼續運行你的提交函數吧(例如是onSubmit或者handleSubmit)。你可以通過在你的處理器函數中調用setSubmitting(false) 來結束生命周期。

FAQ



(1)Q:怎么判定提交處理器(submission handler)正在執行中?
A:當isValidating為false且isSubmitting為true時。

(2)Q:為什么在提交前Formik要“潤色一下(touch)”表單中所有字段?
A:通常,當UI表單中輸入字段被操作過后(Formik中稱為“touched”)只顯示與之相關的錯誤信息。于是,在提交一個表單前,Formik會touch一下所有字段,這樣所有可能隱藏的錯誤都會變得可見。

(3)Q:如何避免兩次重復提交?
A:辦法是當isSubmitting為true時,禁止所有能夠觸發提交的調用。

(4)Q:如何得知表單在提交前正在校驗中?
A:如果isValidating為true而且isSubmitting也為true的話,......

總結

以上是生活随笔為你收集整理的使用Formik轻松开发更高质量的React表单(二)使用指南的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 黄色av电影网址 | 日女人免费视频 | 人妻视频一区二区 | 天堂va蜜桃一区二区三区漫画版 | 法国少妇愉情理伦片 | 亚洲激情在线视频 | 狠狠操亚洲| jizz在线免费观看 | 国模小丫大尺度啪啪人体 | 美女亚洲一区 | 激情综合激情五月 | 午夜av免费在线观看 | 制服丝袜av电影 | 久操伊人网 | 91资源在线播放 | 在线亚洲色图 | 妇女一级片 | 挪威xxxx性hd极品 | 男人的天堂黄色 | 色就是色av | 精品一区二区三区免费 | 日本中文字幕在线免费观看 | 在线色av| 欧美成人二区 | 一区一区三区产品乱码 | 色综合狠狠 | 亚洲精品一区二区三区不卡 | 高清精品xnxxcom | 久久久久国产精品熟女影院 | 色婷婷综合在线 | xxxx日本黄色 | 精品乱子伦一区二区三区 | 超碰国产97 | 国产激情文学 | 秋霞午夜伦理 | 一级大片视频 | 麻豆视频一区二区 | 日免费视频| 日韩视频免费观看高清完整版 | 波多野结衣一区二区在线 | 麻豆出品 | 爱情岛论坛自拍亚洲品质极速最新章 | 99精品人妻无码专区在线视频区 | 中文字幕av免费在线观看 | 男人草女人 | www.人人草 | www.奇米.com | 精品黑人一区二区三区观看时间 | 国产视频第一页 | 国产真实的和子乱拍在线观看 | 欧美一区二区三区免费观看 | 青青草视频 | 黄色欧美网站 | 国产欧美久久久精品免费 | 9·1·黄·色·视·频 | 中文综合网 | 女人av在线| 欧美sm视频 | 东京久久久 | 国产黄色自拍视频 | 99视频一区 | 国产原创麻豆 | 国产视频网站在线观看 | 性生交大片免费看3p | 在线91av| 制服丝袜一区二区三区 | 久久久久人妻一道无码AV | 一级黄大片 | 天堂在线 | 免费一级全黄少妇性色生活片 | 国产嫩草在线观看 | 四虎4hu永久免费网站影院 | 东南亚毛片 | 欧美群交射精内射颜射潮喷 | 九九在线精品 | 中文字幕日韩欧美一区二区三区 | 日本精品久久久久中文字幕 | 成人欧美一区二区三区黑人动态图 | 亚洲激情自拍 | 99热这里只有精品1 亚洲人交配视频 | 国产精品av一区二区 | 欧美色999| 色一情一区二区三区四区 | 国产久久精品 | 蜜桃aaa| 黄色aaaa| 草av在线 | 熟女自拍一区 | 亚洲九九在线 | 一区二区三区 日韩 | 精品人妻一区二区三区免费看 | 国内久久精品 | 成人爽a毛片一区二区免费 日本高清免费看 | 嫦娥性艳史bd | 国产女主播一区 | 香蕉视频在线播放 | 日本泡妞视频 | 久久成人精品视频 | 天天干天天操天天 |