使用Redux从{reducer]返回承诺

时间:2017-04-10 11:57:54

标签: reactjs redux react-redux redux-thunk

我正在使用this starter kit,可以在this fork上找到以下代码。

计数器组件:

export const Counter = (props) => (
  <div style={{ margin: '0 auto' }} >
    <h2>Counter: {props.counter}</h2>
    <button className='btn btn-default' onClick={props.double}>
      Double (Async)
    </button>
  </div>
)
Counter.propTypes = {
  counter     : React.PropTypes.number.isRequired,
  double : React.PropTypes.func.isRequired,
  increment   : React.PropTypes.func.isRequired
}

export default Counter

容器组件:

import { connect } from 'react-redux'
import { increment, double } from '../modules/counter'

import Counter from '../components/Counter'

const mapDispatchToProps = {
  increment : () => increment(1),
  double: () => double()
}

const mapStateToProps = (state) => {
  return {
    counter : state.counter
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter)

行动:

export const COUNTER_INCREMENT = 'COUNTER_INCREMENT'
export const COUNTER_DOUBLE = 'COUNTER_DOUBLE'
// ------------------------------------
// Actions
// ------------------------------------
export const increment = (value = 1) => {
  return {
    type: COUNTER_INCREMENT,
    payload: value
  }
}
export const double = (value = 0) => {
  return {
    type: COUNTER_DOUBLE,
    payload: value
  }
}

const doubleAsync = (state) => {
  return (dispatch, getState) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        dispatch(increment(state))
        resolve()
      }, 200)
    })
  }
}

export const actions = {
  increment,
  double
}


const ACTION_HANDLERS = {

  [COUNTER_INCREMENT]: function (state, action) {
    return state + action.payload
  },
  [COUNTER_DOUBLE]: (state, action) => {
    return doubleAsync()

    }
  }
}

减速器:

const initialState = 0
export default function counterReducer(state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type]
  return handler ? handler(state, action) : state
}

但是COUNTER_DOUBLE动作处理程序似乎没有更新视图,也没有呈现任何内容。我收到了这个警告:

  

警告:道具类型失败:counter类型的道具function无效   提供给Counter,预计number

我意识到我已经定义了一个数字propType并且返回promise函数会导致此错误。我甚至试图修改mapDispatchToProps以返回执行的promise函数无济于事。我做错了什么?

我在这里搜索过,似乎是使用redux-thunk用一个立即执行的函数来包装promise,但是我很难让它工作。

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:5)

默认情况下,redux希望操作成为普通对象。如果您想编写一些异步代码并返回一个承诺,您需要使用某种中间件,password hash and verify here将是一个很好的选择。

redux-thunk的README页面实际上已经完全记录,并且有一个完整的例子。基本上你需要将redux-thunk中间件应用到你的商店,如下所示:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

此外,我建议您阅读有关redux-thunk的redux文档,它有一些很好的例子。

答案 1 :(得分:0)

刚刚在原始仓库上看到了this commit,就是这样。

这是改变:

export const doubleAsync = () => {
  return (dispatch, getState) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        dispatch({
          type    : COUNTER_DOUBLE_ASYNC,
          payload : getState().counter
        })
        resolve()
      }, 200)
    })
  }
}