redux-actions入门

8,359 阅读3分钟

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的使用还是很容易上手的,更多具体细节可以看官方文档