使用Formik轻松开发更高质量的React表单(三)<Formik />
提醒和建议
关于<Formik />组件<Formik>是一个帮助构建表单的组件,它也使用了类似于当前一些流行的库(如React Motion和 React Router)的render这种prop模式。请参考下面的代码: import React from 'react'; import { Formik } from 'formik'; const BasicExample = () => ( <div> <h1>My Form</h1> <Formik initialValues={{ name: 'jared' }} onSubmit={(values,actions) => { setTimeout(() => { alert(JSON.stringify(values,null,2)); actions.setSubmitting(false); },1000); }} render={props => ( <form onSubmit={props.handleSubmit}> <input type="text" onChange={props.handleChange} onBlur={props.handleBlur} value={props.values.name} name="name" /> {props.errors.name && <div id="feedback">{props.errors.name}</div>} <button type="submit">Submit</button> </form> )} /> </div> ); Formik渲染方法<Formik />这个API共提供了三种渲染方法,它们是:
Formik props列表分析上面所有三种渲染方法都会传递相同的props。接下来,我们对props每一个分量作相应的解释。 (1)dirty: boolean当values与初始值不绝对相等时这个属性的值会返回true;否则返回false(Returns true if values are not deeply equal from initial values,false otherwise)。注意:dirty属性是只读的,不应该直接修改它。 (2)errors: { [field: string]: string }其中包含Form校验错误信息。这些信息应当与表单的定义于initialValues中的值(values)保持一致。如果你在使用validationSchema(也推荐你使用),那么数据(原文使用的是“keys and shape”,关于shape一词在React文章中经常见到,这里不便直译)应当与你的模式定义准确匹配。 从内部实现代码来看,Formik会根据你提供的数据转换原始的Yup校验错误信息。如果你在使用validate属性,那么此函数会确定错误对象的具体信息。 handleBlur: (e: any) => void这是onBlur对应的事件处理器函数。当你需要跟踪某个输入字段是否被“动过”(touched)时很有用。用法比如:<input onBlur={handleBlur} ... /> 【注意】本属性仅适用于DOM开发;如果是React Native开发则需使用setFieldTouched代替。 handleChange: (e: React.ChangeEvent<any>) => void这是一个典型的输入字段内容变化时要触发的事件处理器。当key为事件发出的输入字段的name属性时这一调用会更新values。如果name不存在,那么handleChange函数会进一步查找输入字段(input)的id属性。请注意: 这里的input意指所有HTML input标签。 【注意】本属性仅适用于DOM开发;如果是React Native开发则需使用setFieldValue代替。 handleReset: () => void这是表单复位处理器函数,调用它将把表单还原到初始值状态。用法比如:<button onClick={handleReset}>...</button> handleSubmit: (e: React.FormEvent<HTMLFormEvent>) => void这是表单提交处理器函数。 用法比如:<form onSubmit={props.handleSubmit}>...</form>。请结合本系列文章第一篇中「表单提交原理」部分加以理解。 isSubmitting: boolean这个属性值代表了表单提交的当前状态。如果表单在提交中将返回true;否则返回false。重要提醒:一旦你尝试提交表单,Formik就会把这个值设置为true。请结合本系列文章第一篇中「表单提交原理」部分加以理解。 isValid: boolean在不发生错误的情况下这个属性值将为true;或者返回当表单处于pristine条件(例如没有dirty)时会返回isInitialValid的结果值。 isValidating: boolean如果Formik正在运行任何检验函数,则此属性返回true;否则,返回false。想更多地了解在表单提交过程中isValidating属性发生了什么变化,请结合阅读本系列文章第一篇中「表单提交原理」部分。 resetForm: (nextValues?: Values) => void强行复位表单。这个调用会清除所有错误及字段「润色」信息,并且设置isSubmitting为false,设置isValidating为false,并且把mapPropsToValues返回值设置为当前的WrappedComponent的props或者是传递过去的参数。注意:当在componentWillReceiveProps内部调用resetForm时,这是很有用的。 setErrors: (fields: { [field: string]: string }) => void强行设置errors信息。 setFieldError: (field: string,errorMsg: string) => void强行设置给定字段的error信息。注意,这里的参数field应当匹配你希望更新的errors中的key。这个属性在编写定制的输入错误信息处理器函数时非常有用。 setFieldTouched: (field: string,isTouched: boolean,shouldValidate?: boolean) => void强行设置给定字段的touched状态值。注意,这里的参数field应当匹配你想更新的「动过」的key。这个属性在编写定制的blur处理器函数时非常有用。如果validateOnBlur的值设置为true(默认即为此值),那么调用这个方法会触发校验运行。你也可以通过传递第三个参数为false来显式地禁止或者跳过校验。 submitForm: () => void触发表单提交操作。 submitCount: number代表用户尝试提交表单的次数。当调用handleSubmit时此属性的值会加1;但是调用handleReset后该属性值会复位。请注意, submitCount是一个只读属性,不能直接修改。 setFieldValue: (field: string,value: any,shouldValidate?: boolean) => void强制设置一个字段的值。其中,参数field应当匹配你希望更新的values中的key。 该属性在编写定制的change事件处理函数时很有用。当validateOnChange为true (默认即是这个值)时,调用此属性对应的函数会触发校验的执行。当然,你还可以通过传递第三个参数为false来显式地禁止或者跳过校验。 setStatus: (status?: any) => void强制设置一个顶级的状态值。这个调用用于控制你的表单的任意顶级状态。例如,你可以使用它来把API响应传递回在handleSubmit调用中的你的组件内部。 setSubmitting: (isSubmitting: boolean) => void强制设置isSubmitting属性的值。 setTouched: (fields: { [field: string]: boolean }) => void强制设置touched属性的值。 setValues: (fields: { [field: string]: any }) => void强制设置values对象的值。 status?: any这是一个顶级的状态对象,你可以使用它来描述使用其他方法无法表达/存储的表单状态。在捕获或者传递API响应给你的内部组件时这个属性很有用。 touched: { [field: string]: boolean }此属性用于润色表单中对应的字段值。每一个键都相应于一个刚刚被「动过」(touched)或者访问过的字段。 values: { [field: string]: any }这是你的表单中的values对象。其中存储了mapPropsToValues (如果指定的话)对应的结果数据,或者存储那些传递给你的被包装组件(wrapped component)的不是函数形式的props。 validateForm: (values?: any) => void根据指定的方式强制你的validate属性对应的校验函数或者是调用validateSchema。注意,你可以选择性地传递数值进行校验,当然这将相应地修改Formik状态;否则,它会使用表单的当前values。 validateField: (field: string) => void强制调用表单的validate属性对应的函数——如果指定了相应字段的话。Formik将使用当前字段值。 component下面给出此属性的典型使用方法: <Formik component={ContactForm} />; const ContactForm = ({ handleSubmit,handleChange,handleBlur,errors,}) => ( <form onSubmit={handleSubmit}> <input type="text" onChange={handleChange} onBlur={handleBlur} value={values.name} name="name" /> {errors.name && <div>{errors.name}</div>} <button type="submit">Submit</button> </form> }; 【注意】<Formik component> 的优先级会高于<Formik render>;因此,你不要在同一个<Formik>中同时使用二者。 render: (props: FormikProps<Values>) => ReactNode这个属性相当重要,请参考如下代码了解其用法: <Formik render={props => <ContactForm {...props} />} /> <Formik render={({ handleSubmit,errors }) => ( <form onSubmit={handleSubmit}> <input type="text" onChange={handleChange} onBlur={handleBlur} value={values.name} name="name" /> {errors.name && <div> {errors.name} </div>} <button type="submit">Submit</button> </form> )} /> children: func使用方法见下面的代码片断:
//或者使用下面的方式... <Formik> {({ handleSubmit,errors }) => ( <form onSubmit={handleSubmit}> <input type="text" onChange={handleChange} onBlur={handleBlur} value={values.name} name="name" /> {errors.name && <div> {errors.name} </div>} <button type="submit">Submit</button> </form> )} </Formik> enableReinitialize?: boolean默认值为false。此属性用于在initialValues变化时控制是否重置表单。 isInitialValid?: boolean默认值为false。用于控制表单加载前的isValid属性的初始值。你也可以传递一个函数。此属性用于当你想在表单初始加载时启用/禁用一次提交/复位按钮操作时。 initialValues?: Values相应于表单初始字段值。Formik将使用这些值来生成例如props.values这样的方法组件。 即使你的表单默认情况下为空,你也必须使用初始值来初始化所有字段;否则,React会抛出异步,说你已经把一个输入字段从未控制(uncontrolled)状态改变成了可控制(controlled)状态。 onReset?: (values: Values,formikBag: FormikBag) => void对应于你可选择使用的表单复位处理器函数。其中的参数是你的表单values,还有一个"FormikBag"值。 onSubmit: (values: Values,formikBag: FormikBag) => void这是表单提交处理器函数。其中的参数是你的表单values,还有一个"FormikBag"值——其中提供了一个包含被注入的属性(props)和方法(例如所有以set开头——如set<Thing>的方法,还有方法resetForm)的子集的对象,以及传递给包装组件的任何props。 【注意】 errors, touched,status以及所有的事件处理器函数都没有包含在FormikBag参数中。 validate?: (values: Values) => FormikErrors<Values> | Promise<any>【注意】Formik作用特别推荐我们使用validationSchema和Yup实现表单校验。无论如何,表单校验应该使用一种相对独立的,比较直观的方式实现——这也是每一个所希望的。 另外,你可以使用同步或者异步函数来实现表单校验。请参考下面的代码: (1)同步校验方式(返回一个errors对象) // Synchronous validation const validate = (values,props) => { 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; }; (2)异步校验方式(返回errors对象中的一个代表错误的Promise) // Async Validation const sleep = ms => new Promise(resolve => setTimeout(resolve,ms)); const validate = (values,props) => { return sleep(2000).then(() => { let errors = {}; if (['admin','null','god'].includes(values.username)) { errors.username = 'Nice try'; } // ... if (Object.keys(errors).length) { throw errors; } }); }; validateOnBlur?: boolean此属性的默认值为true。你可以在表单blur事件触发时使用这个属性——更具体一些说,无论是调用handleBlur,setFieldTouched还是setTouched都可以。 validateOnChange?: boolean此属性的默认值为true。当表单触发change事件或者相关事件时你可以使用这个属性告诉Formik进行有关校验。 更具体一些说,无论是调用handleChange,setFieldValue还是setValues都可以。 validationSchema?: Schema | (() => Schema)这个属性非常重要,用于定义Yup模式( schema)或者是一个返回Yup模式的函数,用于校验任务。其中,Errors会通过key映射到内部组件的errors。这个属性的keys应当与values中的相匹配。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |