使用 Redux 从 reducer 返回一个 promise
Returning a promise from a reducer with Redux
我正在使用 this starter kit and the code below can be found on 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
操作处理程序似乎没有更新视图,也没有呈现任何内容。我收到此警告:
Warning: Failed prop type: Invalid prop counter
of type function
supplied to Counter
, expected number
.
我意识到我已经定义了一个数字 propType
并且 return 承诺函数导致了这个错误。我什至尝试将执行的承诺功能修改 mapDispatchToProps
为 return 无济于事。我做错了什么?
我在这里搜索过,似乎一致认为使用 redux-thunk 将 promise 包装在一个立即执行的函数中,但我很难让它工作。
如有任何帮助,我们将不胜感激!
默认情况下,redux 期望动作是普通对象。如果您想编写一些异步代码和 return 承诺,您需要使用某种中间件,redux-thunk 将是一个不错的选择。
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)
);
此外,我建议您阅读有关 async action creators 的 redux 文档,其中有一些很好的示例。
刚刚在原始仓库中看到 this commit 正是这样做的。
这是变化:
export const doubleAsync = () => {
return (dispatch, getState) => {
return new Promise((resolve) => {
setTimeout(() => {
dispatch({
type : COUNTER_DOUBLE_ASYNC,
payload : getState().counter
})
resolve()
}, 200)
})
}
}
我正在使用 this starter kit and the code below can be found on 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
操作处理程序似乎没有更新视图,也没有呈现任何内容。我收到此警告:
Warning: Failed prop type: Invalid prop
counter
of typefunction
supplied toCounter
, expectednumber
.
我意识到我已经定义了一个数字 propType
并且 return 承诺函数导致了这个错误。我什至尝试将执行的承诺功能修改 mapDispatchToProps
为 return 无济于事。我做错了什么?
我在这里搜索过,似乎一致认为使用 redux-thunk 将 promise 包装在一个立即执行的函数中,但我很难让它工作。
如有任何帮助,我们将不胜感激!
默认情况下,redux 期望动作是普通对象。如果您想编写一些异步代码和 return 承诺,您需要使用某种中间件,redux-thunk 将是一个不错的选择。
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)
);
此外,我建议您阅读有关 async action creators 的 redux 文档,其中有一些很好的示例。
刚刚在原始仓库中看到 this commit 正是这样做的。
这是变化:
export const doubleAsync = () => {
return (dispatch, getState) => {
return new Promise((resolve) => {
setTimeout(() => {
dispatch({
type : COUNTER_DOUBLE_ASYNC,
payload : getState().counter
})
resolve()
}, 200)
})
}
}