1

redux-form学习笔记

我们为什么要用redux-form

在我们现在的后台项目里用到了很多的form表单,开始我们根据react官方提供的方法是要给每一个input或者select设置一个onChange方法,来监听表单value值的变化,然后通过setState方法设置新的state,再重新渲染页面,同时,我们首先就不得不讲props里的数据放到了state里面,我们就需要同时维护这两种数据,后来我们觉得这种方式其实不是很适合后台这样的大量表单的项目。
后来,我们尝试使用给表单设置ref属性,并且通过defaultValue属性进行初始化,然后通过React.findDOMNode(this.refs.item).value的方式来获取表单中的值然后传递给action,这样看起来貌似是清晰了一点,但是这里有两个问题,其一是findDOMNode这种方式的性能貌似不怎么样,官方并不推荐大量使用,其二数据校验也不如上一种方便。
就是这样,我们又尝试了终极解法,也就是今天的主角redux-form

redux-form能够解决我们现在的哪些问题

  1. 只有一份数据需要维护也就是fields里面的数据,fields是一个数组,这里面的数据就是表单中的需要动态改变的项

  2. 方便的初始化设置 initialValues属性

  3. 丰富的数据校验方式,支持同步校验和异步校验

  4. 获取表单数据,直接handleSubmit方法即可接收表单数据。
    上面这四部分几乎包含了我们现在后台几乎会用到的所有功能,接下来我会逐步讲解具体的用法。

用法示例解析

使用redux-form,在我们reducer文件夹下的index.js文件中,加入下面的代码。

export { reducer as form } from ‘redux-form’

这样在我们的devTools中就会看到数据节点里面会多处一个form
在这里我觉得要说出一个个人的感受,我觉得redux-form其实就是一个临时存储表单数据的仓库,我们把数据放进去,然后在仓库里面做校验,看看储物是否合法,然后将合法的数据提交给我们指定的action。
好了,下面来针对第二步的问题作解析
(1) fields
field里面的数据,其实就是给每个表单项设置了一个唯一的key,也可以称之为这个表单的字段名。这样讲可能不是很明白,来对比着看两段代码吧。

const { fields: {name, address, phone}, handleSubmit } = this.props
<input type="text" {...name} />

这里要声明一下,fields其实并不是从它的父组件传过来的,其实是从redux-form传过来,在field声明的这几个变量,就是告诉redux-form,你要管理哪些个input框,在做校验和提交的时候会校验以及提交哪些个表单项里面的值。虽然它很重要,但他真的仅仅只是一个声明而已哈
(2) 初始化表单
这个也是根据我们后台功能的需求来说的,在对某一项进行编辑的时候我们要显示原始的还未变更的数据在表单中,用redux-form其实也很容易.

export default reduxForm({
    form: 'formname',
    fields,
    initailValus: data
})(formClassName)

只需要加一个initialValue属性即可,其中data的属性名中对应我们要初始化的表单的字段名,例如{name: 'wupengyu'}
(3)数据校验
数据校验其实应该分成三部分,其中第一部分是同步校验数据,第二部分就是提示错误信息,第三部分是异步校验数据
首先来说同步校验

export default reduxForm({
    form: 'formname',
    fields,
    validate: formValidate
})(formClassName)

加入validate属性,其中formValidate如下

const formValidate = values => {
  const errors = {}
  if (!values.name) {
    errors.name = 'Required'
  } else if (values.name.length > 15) {
    errors.name = 'Must be 15 characters or less'
  }
  return errors
}

redux-form会把表单数据传递个validate方法,我们即可在validate方法中校验数据,并返回错误信息
提示错误信息
直接上代码

<div>
  <div>
    <input type="text" placeholder="name" {...name}/>
  </div>
  {user.touched && user.error && <div>{user.error}</div>}
</div>

我们这里关注的其实只是这段代码{user.touched && user.error && <div>{user.error}</div>},其中touched是每一个fields里面的值都有的属性,当input被点击时会被设置成ture,error也是rudux-form的一个属性,它里面的属性其实就是formValidate返回的错误信息。
如果这个字段被校验有错误则显示错误信息,当然redux-form里还有很多其他的属性可用于校验,例如valid,invalid, pristine, dirty等。
异步校验

const asyncValidate = (values/*, dispatch */) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (['wupengyu'].includes(values.name)) {
        reject({name: 'NAME_REPEATE'})
      } else {
        resolve()
      }
    }, 1000) // simulate server latency
  })
}

与同步校验一样,这是在异步校验过程中我们要等待promise对象返回后对数据进行校验,我觉得在这里就可以完全取代saveType了
(4)获取数据
如果是传递给父组件的handleSubmit方法

<button onClick={handleSubmit}>Submit</button>

即可讲表单中的数据提交给父组件
如果是要传递个自己的某个方法的话

<button onClick={handleSubmit(this.save.bind(this))}></button>

wupengyu
1.8k 声望166 粉丝

写作是为了更好的思考


引用和评论

0 条评论