Redux 是 JavaScript 状态容器,提供可预测化的状态管理。但是同时它也让状态管理变得很冗长,大量的action、actionCreator、reducer让人不断在写重复的代码。
redux-actions是一个实用的库,让编写redux状态管理变得简单起来。redux-action产生的动作是FSA标准的。
计数器例子
createAction
首先先来写action和actionCreator:
// action.js
import { createAction } from "redux-actions"
export const INCREMENT = 'INCREMENT'
export const increment = createAction(INCREMENT)
复制代码
上边代码定义一个动作INCREMENT
, 然后通过createAction
创建了对应actionCreator。调用increment()
就会返回{ type: 'INCREMENT' }
, 调用increment(10)
返回{ type: 'INCREMENT', payload: 10 }
createAction
是用来创建动作创建器的函数。
createAction(
type, // 动作名
payloadCreator = Identity, // 用来创建动作对象中的payload值,默认使用lodash的Identity
?metaCreator // 用来创建动作对象中元数据
)
const increment = createAction(
'INCREMENT',
mount => mount,
() => ({ admin: true })
);
increment(20);
// {
// type: 'INCREMENT',
// payload: 20,
// meta: { admin: true },
// }
复制代码
handleAction
接着用handleAction
来处理动作
// reducer.js
import {handleAction} from 'redux-actions'
import {INCREMENT} from './action'
const defaultState = { count: 1 }
const reducer = handleAction(
INCREMENT,
(state, action) => ({
count: state.count + action.payload
}),
defaultState
)
export default reducer
复制代码
handleAction
会返回一个reducer,后续用这个reducer来创建store。
// type为动作类型, reducer为动作处理, defaultState为默认状态
handleAction(type, reducer, defaultState)
// 上面的createAction效果就等同下面
const reducer = (state = defaultState, action) {
switch(action.type) {
case 'INCREMENT':
return {
count: state.count + action.payload
}
default:
return state
}
}
复制代码
串联
最后把对应的代码补充完整即可。
// Counter.js
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {increment} from './action'
import {bindActionCreators} from 'redux'
@connect(
state => ({count: state.count}),
dispatch => ({increment: bindActionCreators(increment, dispatch)})
)
class Counter extends Component {
render () {
return (
<div>
<button onClick={this.props.increment.bind(this, 1)}>add</button>
<div>{this.props.count}</div>
</div>
)
}
}
复制代码
// app.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {createStore} from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
class App extends Component {
render() {
return (
<Provider store={store}>
<div>
<h3>Redux-actions</h3>
<Counter/>
</div>
</Provider>
);
}
}
复制代码
更多API
通过上面的例子,你应该可以对redux-actions有了基本的认识了。接下来继续介绍其他API
createActions
从名字就可以看出这个函数用来创建多个动作的。具体用法就是createActions(actionMap)
actionMap就是一个对象,key值为动作类型,value可以是payloadCreator函数、一个数组[payloadCreator, metaCreator]、嵌套的actionMap。
cosnt {add, remove} = createActions({
ADD_TODO: todo => ({ todo }), // payload creator
REMOVE_TODO: [
todo => ({ todo }), // payload creator
(todo, warn) => ({ todo, warn }) // meta
]
})
// {type: 'ADD_TODO', payload: {todo: 'redux-actions'}}
add('redux-actions')
// {type: 'ADD_TODO', payload: {todo: 'redux-actions'}, meta: {todo: 'redux-actions', warn: 'warn'}}
remove('redux-actions', 'warn')
复制代码
handleActions
同样的handleActions函数是用来处理多个动作的。
handleActions(reducerMap, defaultState)
const reducer = handleActions(
{
INCREMENT: (state, action) => ({
counter: state.counter + action.payload
}),
DECREMENT: (state, action) => ({
counter: state.counter - action.payload
})
},
{ counter: 0 }
);
复制代码
可以看到reducerMap中key就是动作名, value就是reducer
combineActions
合并多个action和actionCreator
const { increment, decrement } = createActions({
INCREMENT: amount => ({ amount }),
DECREMENT: amount => ({ amount: -amount }),
})
const reducer = handleAction(combineActions(increment, decrement), {
next: (state, { payload }) => ({ ...state, count: state.count + payload }),
throw: state => ({ ...state, count: 0 }),
}, { count: 10 })
const reduce2 = handleActions(
{
[combineActions(increment, decrement)] (state, {payload}) {
return { ...state, count: state.count + payload }
}
},
{ count: 10 }
)
复制代码
增加和减小的逻辑基本一致,所以可以使用combineActions来合并简写。
总结
redux-actions的使用还是很容易上手的,更多具体细节可以看官方文档