通过一个例子,以开发的视角,说明 redux 用法
GitHub地址: https://github.com/itainf/demo-react
体验地址:http://wojson.com/demo/demo-react/hello.html
action
action 描述事件的发生,text 是调用者传递的参数
本例在 actions/index.jsx 代码, 其实是一个普通的函数,描述了一个ADD_USER事件,接收一个text参数
白话描述: 现在告诉你发起一个 ADD_USER 操作,传递给你text参数
export const addUser= text => {
return {
type: 'ADD_USER',
user:text
}
}
dispatch
dispatch 用来派发 action 的事件描述 ,dispatch 将action的事件描述传递给 Reducers
白话描述: 有一个人需要新增一个用户操作,并且给出参数 {name:‘zhangsan’,sex:‘男’,age:18} ,你们Reducers 谁来处理
本例中 containers/AddUser.jsx 代码, addUser(val) 是一个普通action方法调用,传递了val参数,得到一个事件描述 ,这个描述其实也是一个普通的JavaScript对象(参考下面派发给Reducers 的数据格式)
return {
handSubmit: (val) => {
dispatch(addUser(val))
}
}
dispatch 派发了这个事件描述, 如果 val的值是
{
"name": "zhangsan",
"sex": "男",
"age": "18"
}
最终派发给 **Reducers ** 的事件描述就是:
{
"type": "ADD_USER",
"user": {
"name": "zhangsan",
"sex": "男",
"age": "18"
}
}
Reducer
**Reducer ** 指定了如何响应 actions 的事件描述,更新state
本例中 reducers/updateUserList.jsx 代码, updateUserList 接收state和 action 参数,根据action更新旧的sate
action 参数就是通过 dispatch 派发过来的事件描述 , 内容和上面传过来的一样:
{
“type”: “ADD_USER”,
“user”: {
“name”: “zhangsan”,
“sex”: “男”,
“age”: “18”
}
}
state参数 是旧的数据
const updateUserList = (state=[] , action) => {
switch (action.type) {
case 'ADD_USER':
return [ ...state,
{
name: action.user.name,
sex: action.user.sex,
age: action.user.age
}]
default:
return state
}
}
reducer 更新的state 会被组件容器监听到,然后传递给展示组件
containers容器组件
描述如何运行(数据获取、状态更新)
本例中 containers/AddUser.jsx 代码, 容器组件和展示组件的属性做一个映射, 容器组件会监听到 Redux state 的变化,提供给展示组件
mapStateToProps 映射属性
mapDispatchToProps 映射函数
//mapStateToProps 将更新后的状态数据传递给展现组件,本例中会将 buttonName 传递给展示组件
//state: state参数接收通过 reducer 变更过后的数据
//state.setButtonName 其实就是获取了变更后的数据
const mapStateToProps = state => {
return {
buttonName:state.setButtonName
}
}
//mapDispatchToProps 将handSubmit函数传递给展示组件
const mapDispatchToProps= dispatch => {
return {
handSubmit: (val) => {
dispatch(addUser(val))
}
}
};
// 将容器和展示组件关联起来
const AddUserForm = connect(
mapStateToProps,
mapDispatchToProps
)(SearchForm)
export default AddUserForm
components展示组件
描述如何展现(骨架、样式)
容器映射的参数会通过 props 传递过来, {props.buttonName} 就是获取容器传过来的按钮名称
const SearchForm = ( props ) => {
let input1, input2, input3 ;
return (
<div>
<form
onSubmit={e => {
e.preventDefault();
if (!input1.value.trim()) {
return
}
props.handSubmit({
name:input1.value,
sex:input2.value,
age:input3.value,
} ) ;
input1.value = '';
input2.value = '';
input3.value = '';
}}
>
<table>
<tr>
<td>姓名:
<input ref={node => {
input1 = node
}}
type='text'/>
</td>
<td>性别:<input ref={node => {
input2 = node
}} type='text'/></td>
<td>年龄<input ref={node => {
input3 = node
}} type='text'/></td>
<td>
<button type="submit">
{props.buttonName}
</button>
</td>
</tr>
</table>
</form>
</div>
)
}
export default SearchForm