本文将继续我学习redux-form的总结部分,在这一部分中,我将对官方示例SelectingFormValuesForm给出简要解析,不当处还希望同志们批评指正。
示例SelectingFormValuesForm简介
本示例原意重在介绍formValueSelector这个redux-form API的用法的。官文上说,在我们的表单中有时候想访问表单中另外一些字段值时可以使用这个API。不过,要使用这个formValueSelector API,我们需要使用connect方法把表单中的有关字段值直接连接到Redux store上。
但是,官方还提出警告:要小心使用上面这个API,因为每当表单中有关字段值改变时整个表单都会重新渲染,从而影响系统性能。
示例中有关代码分析
在redux-demo的大多数示例中,关键代码都在于表单(也是react-redux容器)
定义部分。下面给出表单SelectingFormValuesForm的定义代码:
SelectingFormValuesForm.js import React from 'react' import { connect } from 'react-redux' import { Field,reduxForm,formValueSelector } from 'redux-form' let SelectingFormValuesForm = props => { const { favoriteColorValue,fullName,handleSubmit,hasEmailValue,pristine,reset,submitting } = props return ( <form onSubmit={handleSubmit}> <div> <label>First Name</label> <div> <Field name="firstName" component="input" type="text" placeholder="First Name" /> </div> </div> <div> <label>Last Name</label> <div> <Field name="lastName" component="input" type="text" placeholder="Last Name" /> </div> </div> <div> <label htmlFor="hasEmail">Has Email?</label> <div> <Field name="hasEmail" id="hasEmail" component="input" type="checkBox" /> </div> </div> {hasEmailValue && ( <div> <label>Email</label> <div> <Field name="email" component="input" type="email" placeholder="Email" /> </div> </div> )} <div> <label>Favorite Color</label> <div> <Field name="favoriteColor" component="select"> <option /> <option value="#ff0000">Red</option> <option value="#00ff00">Green</option> <option value="#0000ff">Blue</option> </Field> </div> </div> {favoriteColorValue && ( <div style={{ height: 80,width: 200,margin: '10px auto',backgroundColor: favoriteColorValue }} /> )} <div> <button type="submit" disabled={pristine || submitting}> Submit {fullName} </button> <button type="button" disabled={pristine || submitting} onClick={reset}> Clear Values </button> </div> </form> ) } // The order of the decoration does not matter. // Decorate with redux-form SelectingFormValuesForm = reduxForm({ form: 'selectingFormValues' // a unique identifier for this form })(SelectingFormValuesForm) // Decorate with connect to read form values const selector = formValueSelector('selectingFormValues') // <-- same as form name SelectingFormValuesForm = connect(state => { // can select values individually const hasEmailValue = selector(state,'hasEmail') const favoriteColorValue = selector(state,'favoriteColor') // or together as a group const { firstName,lastName } = selector(state,'firstName','lastName') return { hasEmailValue,favoriteColorValue,fullName: `${firstName || ''} ${lastName || ''}` } })(SelectingFormValuesForm) export default SelectingFormValuesForm
上面代码的关键点并不多。第一,注意import语句导入的connect方法,还有reduxForm和formValueSelector两个方法的导入。
第二,接下来通过“let SelectingFormValuesForm=props=>{...}”语句定义表单SelectingFormValuesForm。注意它的剪头函数的参数props中除了系统内置的属性和方法定义外,还加入了定制的三个属性(vavoriateColorValue,fullName和hasEmailValue)的定义。
API函数的使用
formValueSelector API的直接使用,主要体现在如下几句代码中:
// Decorate with connect to read form values const selector = formValueSelector('selectingFormValues') // <-- same as form name SelectingFormValuesForm = connect(state => { // can select values individually const hasEmailValue = selector(state,fullName: `${firstName || ''} ${lastName || ''}` } })(SelectingFormValuesForm)
易见,上面代码中第一行创建了一个selector函数,这是通过调用API formValueSelector实现的,传递的参数是经过上面reduxForm封装的容器表单SelectingFormValuesForm(注意,上面为了偷懒,创建表单的变量名与由reduxForm方法返回的表单包装以后的对象名是一样的——这是经包装以后的对象,实际上也是一个容器组件)。观察源码的话,你会注意到reduxForm方法内部重点调用了connect方法。
有关connect方法的作用,文后的参考中已作了详细的分析,主要有两点:
(1)此方法的作用在把React组件与Redux store连接到一起。
(2)此方法没有修改传入的React组件,而返回一个新的已经与Redux store连接的组件。
接下来再往下看,上面代码中接着显式调用connect方法,此方法的第一个参数通常命名为mapStateToPros,意即把系统Store中的state转换成各组件能够访问的props。在上面代码中,通过调用了前面刚刚创建的selector函数(两个参数含义明显,略述),得到state中存储的对应内容的一个副本。特别注意下面一句:
const { firstName,'lastName')
这里通过ES6的解构赋值,一次性取得一组值。最后,此函数(connect的第一个参数)返回一个新的对象,注意到对象的前两个键值与键重名(ES6特性),第三个键则是一个新生成的键名。
可以看出,上面return语句返回的对象的各个属性正对应于上面表单组件定义时props提供的几个自定制属性。这几个数据是怎么告诉给表单组件的呢?这要归功于connect()方法。
补充
connect()方法是react-redux库的核心方法之一,典型使用在定义包括上面的表单组件在内的容器组件的模块中,而且可以多次嵌套式地使用,具体情形则根据需要而定。
小结
总起来讲,是否使用本文提供的API formValueSelector,请谨记本文前提加粗的官方提醒的一句,不是非用不可,而是用巧了可以简单编码,在多表单多字段情况下用不好则导致影响系统性能!
参考资料
1.http://taobaofed.org/blog/2016/08/18/react-redux-connect/
2.https://www.jianshu.com/p/9873d4ccb891
3.https://github.com/lipeishang/react-redux-connect-demo/blob/master/public/src/containers/App.js
4.http://www.jb51.cc/article/p-zpibqjsl-bmq.html
5.https://redux-form.com/7.4.2/docs/gettingstarted.md/