本系列文章学习和研究redux-form的主要参考资源,特别是代码部分,主要在于其官方网站提供的一切资源及工程源码剖析。

基础

在使用 redux-form 之前,需要用户具备以下基础:


  • HTML5+CSS3
  • ES6+高阶组件函数式编程思想+React
  • Redux及React-redux

redux-form核心模块

redux-form基于React-Redux状态管理理念,而form本身作为一种「特殊」的容器组件,要实现这种组件与数据中心(即Redux的store)的交互,关键在于把握 redux-form 的三个主要模块:

  • formReducer reducer : 表单的各种操作以 Redux action 的方式,通过此 reducer 来促成 Redux store 数据的变化。
  • reduxForm() API :此高阶组件用以整合 Redux action 绑定的用户交互与您的组件,并返回一个新的组件供以使用。
  • <Field/> API: 用此代替您原生态的HTML5 <input/> 组件,可以与redux-form的逻辑相连接。

补充解释如下。

(一)关于redux-form的reducer

有关代码如下(store.js):

import { reducer as reduxFormReducer } from 'redux-form';const rootReducer = combineReducers({//other custom reducersform: reduxFormReducer, // mounted under "form"
});

combineReducers工具函数组件各个子reducer,最后形成一个大型reducer,称为rootReducer。然后,以此rootReducer为参数传递给createStore创建Redux的store对象。

Reducer的作用是:负责根据子组件发出的Action和原有State生成新的State,即:

Reducer的作用
oldState+Action=>newState

为了全面理解上面的代码,让我们再回顾一下Redux编程中Reducer拆分思想。Redux编程思想中建议把较大型的超过20行以上代码的reducer函数拆成了若干个小型的recducer函数,每一个负责生成对应的一部分state。而且,这种拆分与 React 应用的结构相吻合:一个 React 根组件由很多子组件构成。这就是说,子组件与子 Reducer 完全可以一一对应。

Redux 提供的combineReducers方法,正是用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,即可将它们合并成一个大的 Reducer。

典型情况下,上述combineReducers方法用场是:
生成rootReducer的模块中。因为往往随后使用rootReducer作为参数并通过调用createStore方法生成整个系统唯一的store,所以,combineReducers方法主要store.js模块中。

关于combineReducers方法还有一个重要细节,请注意如下代码:

const rootReducer = combineReducers({chatLogReducer,statusMessageReducer,userNameReducer,form: reduxFormReducer
});

这种写法有一个前提: State 的属性名必须与各个子 Reducer 同名;否则,就要采用下面的写法

const rootReducer = combineReducers({
chatLog:chatLogReducer,
statusMessage:statusMessageReducer,
userName:userNameReducer,
form: reduxFormReducer
});
因此,该函数根据 State 的 不同key 去执行相应的子 Reducer,并将返回结果合并成一个大的 State 对象。注意:最后一个form键名是不能更改的,这是redux-form系统规定的

将来使用上面代码的结果的方法是:
state.chatLog、state.statusMessage......
当然,由于一个典型的reducer是要返回一个新的状态——一般使用对象方式表示;所以,最终你会见到代码中出现类似于下面的引用形式:
state.chatLog.obj1.p1

这一点在redux-form官方网站提供的实例InitializeFromStateForm中文件InitializeFromStateForm.js中即有如下使用方式:

InitializeFromStateForm = connect(
state => ({
initialValues: state.accountReducer.data,
}),
{ load: loadAccount },
)(InitializeFromStateForm);

上面代码行出现在示例表单定义模块的代码中,这里通过connect方法调用进一步包装表单组件,实现把store中state有关数据(state.accountReducer.data)映射到表单组件的属性上。

啰嗦上面这一些,就是为了强调一个简短的combineReducers调用意义重大,正是这一调用最终把store数据(代码中典型称为state)与组件props关联到一起。

(二)关于reduxForm()方法

API部分的描述是:reduxForm(config:Object)
这里,参数config是一个对象类型。此对象规定了系统内置的许多key,分别实现不同的功能。此高阶组件方法用以整合 Redux action绑定的用户交互与您的组件,并返回一个新的组件供以使用。

上面示例中的代码用法如下:

InitializeFromStateForm = reduxForm({form: 'initializeFromState', // a unique identifier for this form
})(InitializeFromStateForm);InitializeFromStateForm = connect(state => ({initialValues: state.accountReducer.data, // pull initial values from account reducer}),{ load: loadAccount }, // bind account loading action creator
)(InitializeFromStateForm);

上面reduxForm方法调用至少有两层含义:

(1)此方法进一步封装上面定义的表单组件,从而实现组成表单的UI组件的属性(props)(包括表单具体定义中的各个内置属性与接下来通过connect创建的少数定制属性,例如load)与store中的数据(即state,这个state中的对应形式可能是对象也可能是函数)关联到一起。

(2)此方法返回一个新的表单组件,提供给index.js中ReactDOM.render方法最终渲染网页中的表单使用,有关代码如下:

ReactDOM.render(<Provider store={store}><div style={{ padding: 15 }}><h2>Initialize From State</h2><InitializeFromStateForm onSubmit={showResults} /><Values form="initializeFromState" /></div></Provider>,rootEl
);

(三)关于<Field/>组件

所有需要与 store 数据连接的表单组件,都可以用 <Field/>。在正确使用它之前,需要清楚三条基本概念:


  • 必须包含 name 属性。可以是简单的字符串,如 userName、password,也可以是复杂的结构,如 contact.billing.address[2].phones[1].areaCode。
    * 必须包含 component 属性。可以是一个组件、无状态组件或者DOM所支持的默认的标签(input、textarea、select)。
  • 其他所有属性会通过prop传递到元素生成器中,如 className。

使用方法列举如下:

1.组件

可以是任何自定义的 class 组件(如下面的MyCustomInput组件),或者其他第三方库。

/```
/ MyCustomInput.js
import React, { Component } from 'react'

class MyCustomInput extends Component {
render() {
const { input: { value, onChange } } = this.props
return (
<div>
<span>The current value is {value}.</span>
<button type="button" onClick={() => onChange(value + 1)}>Inc</button>
<button type="button" onClick={() => onChange(value - 1)}>Dec</button>
</div>
)
}
}

然后这样使用:

import MyCustomInput from './MyCustomInput'

//...

<Field name="myField" component={MyCustomInput}/>


### 2.无状态组件这是一个非常灵活的使用 <Field/> 的方法。你必须在你的 render() 方法外定义它,否则它每次渲染都会被重建,并且由于组件的 prop 会变,就会强制 <Field/> 进行渲染。如果你在 render() 内部定义无状态组件,不但会拖慢你的程序的运行,而且组件的input每次都会在组件重新渲染的时候失去焦点。//在方法 render() 外定义
const renderField = (field) => (<div className="input-row"><input {...field.input} type="text"/>{field.meta.touched && field.meta.error &&<span className="error">{field.meta.error}</span>}</div>)//在render()方法内定义
<Field name="myField" component={renderField}/>### 3.最简单且最常用的形式: input, select, or textarea比如创建一个文字输入框组件

<Field component="input" type="text"/>

# 参考
(1)https://github.com/tedyuen/react-redux-form-v6-example#field-value-lifecycle
(2)http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
(3)https://redux-form.com/7.4.2/docs/gettingstarted.md/

redux-form(V7.4.2)笔记( 五)核心模块回顾相关推荐

  1. node.js学习笔记5——核心模块1

    node.js学习笔记5--核心模块1 Node.js核心模块主要内容包括:(1)全局对象 (2)常用工具 (3)事件机制 (4)文件系统访问 (5)HTTP服务器与客户端 一: 全局对象 Node. ...

  2. Netty工作笔记0066---Netty核心模块内容梳理

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152

  3. Netty工作笔记0053---Netty核心模块梳理

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152

  4. Netty工作笔记0051---Netty核心模块2

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 selector channelhandler

  5. Netty工作笔记0050---Netty核心模块1

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152

  6. SpringCloud 学习笔记五 多模块搭建-搭建Order模块

    前面我们已经搭建好了两个模块,现在我们继续搭建一个子order模块, 搭建好了以后我们实现简单版的服务通信 直接上代码 ,pom配置: <dependency> <!--该依赖集成了 ...

  7. [笔记]Windows核心编程《二十》DLL的高级操作技术

    系列文章目录 [笔记]Windows核心编程<一>错误处理.字符编码 [笔记]Windows核心编程<二>内核对象 [笔记]Windows核心编程<三>进程 [笔记 ...

  8. [笔记]Windows核心编程《十六》线程栈

    系列文章目录 [笔记]Windows核心编程<一>错误处理.字符编码 [笔记]Windows核心编程<二>内核对象 [笔记]Windows核心编程<三>进程 [笔记 ...

  9. [笔记]Windows核心编程《十九》DLL基础

    系列文章目录 [笔记]Windows核心编程<一>错误处理.字符编码 [笔记]Windows核心编程<二>内核对象 [笔记]Windows核心编程<三>进程 [笔记 ...

  10. 哈工大操作系统学习笔记五——内核级线程实现

    哈工大os学习笔记五(内核级线程实现) 文章目录 哈工大os学习笔记五(内核级线程实现) 一. 中断入口.中断出口(前后两段) 1. 从int中断进入内核(中断入口第一段) 2.中断出口(最后一段) ...

最新文章

  1. python 十进制转二进制,十进制转八进制,十进制转十六进制 的方法
  2. 开发者账号申请完多久可以用_苹果开发者从0到发布app到apple store
  3. php 鸟哥写过的c扩展,Yaconf —— 高性能的 PHP 配置管理扩展,鸟哥出品哦~
  4. Android顶部粘至视图具体解释
  5. Java Enum学习总结
  6. 当罗密欧遇到朱丽叶... ...当指针遇到数组
  7. C语言-printf变参函数与它的实参转换/转换模板
  8. Cocos-2d 关于SwallowTouch,进一步解释触摸事件分发机制
  9. SQL 常用脚本大全
  10. 虚化4独立游戏开发第一章:策划案
  11. 关于扫码点餐多人实时共享订单的思考
  12. matlab 复权数据,用Pandas计算前复权数据
  13. UART(Universal Asynchronous Receiver/Transmitter)
  14. 显著性检验的“前世与今生”
  15. 视频消重入门级,学会这个你基本就能靠搬运维持生活自媒体视频如何消重?批量处理去重消重去水印去logo...
  16. 算法:记忆化搜索算法
  17. jar包(依赖jar 运行jar)
  18. Cauchy–Schwarz inequality理解
  19. 韦东山 IMX6ULL和正点原子_「正点原子Linux连载」第四十三章Linux设备树(一)
  20. 微模块化炙手可热,数据中心走向智能化取胜

热门文章

  1. php 判断访问类型,php如何判断访问系统的用户设备类型(代码示例)
  2. 219.存在重复元素II
  3. 187.重复的DNA序列
  4. HDF5 library version mismatched error
  5. anaconda conda 切换为清华源
  6. Cannot open D:\Program Files\Anaconda\Scripts\pip3-script.py
  7. ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any()
  8. 支持向量机(Support Vector Machine SVM)
  9. antd vue form 手动校验_vue测试模板与jsonSchema自动生成elment组件
  10. 为什么InnoDB表要建议用自增列做主键而MyISAM不需要