Redux 调用 dispatch 函数但它不会改变 store
Posted
技术标签:
【中文标题】Redux 调用 dispatch 函数但它不会改变 store【英文标题】:Redux calls dispach function but it does not change the store 【发布时间】:2018-05-09 11:24:10 【问题描述】:我正在写LoadingComponent
,它应该在加载一些数据时返回Spinner
,完成后它应该返回this.props.children
。
我在componentWillMount
获取数据:
class LoadingComponent extends React.Component
componentWillMount()
this.props.userActions.onUserAuthChange();
this.props.currencyActions.getCurrencies();
我检查是否正在加载用户或货币之一,如果是,则返回 Spinner
:
render()
const loadingUser, loadingCurrencies = this.props;
if (loadingCurrencies || loadingUser)
return (
<Spinner/>
)
return (
this.props.children
)
这是我将state
连接到props
的地方:
const mapStateToProps = state => (
user: state.user,
loadingUser: state.loading.loadingUser,
loadingCurrencies: state.loading.loadingCurrencies,
);
const mapDispatchToProps = dispatch => (
userActions: bindActionCreators(userActions, dispatch),
currencyActions: bindActionCreators(currencyActions, dispatch),
);
const ConnectedLoading = connect(mapStateToProps, mapDispatchToProps)
(LoadingComponent);
export default withRouter(ConnectedLoading);
还有loadingReducer
:
const loadingReducer = (state = initialState.loading, action) =>
switch (action.type)
case actionTypes.LOADING:
return ...state, isLoading: action.loading;
case actionTypes.LOADING_USER:
return ...state, loadingUser: action.loadingUser;
case actionTypes.LOADING_CURRENCIES:
return ...state, loadingCurrencies: action.loadingCurrencies;
default:
return state;
;
问题是loadingUser
和loadingCurrencies
总是错误的。这是getCurrencies
函数,它在数据开始下载时以 true 调度,之后以 false 调度:
export const getCurrencies = () => async dispatch =>
try
dispatch(loadingCurrencies(true));
const currencies = await get();
dispatch(loadCurrencies(currencies.rates));
dispatch(loadingCurrencies(false));
catch (e)
我在 App.js 中使用 LoadingComponent:
render()
return (
<LoadingComponent>
<div className='App'>
<Route path='/:lang' render=props =>
languages.hasOwnProperty(props.match.params.lang) ?
<Navbar ...props/> :
<Redirect to=`/$defaultLanguage`/>
/>
<Layout/>
</div>
</LoadingComponent>
)
这是监听loadCurrencies(currencies.rates)
的reducer函数:
const currencyReducer = (state = initialState.currency, action) =>
switch (action.type)
case actionTypes.LOAD_CURRENCIES:
return ...state, currencies: action.currencies;
case actionTypes.CHANGE_CURRENCY:
return ...state, current: action.current;
default:
return state;
在调试过程中注意到LoadingComponent
Redux 开发工具未激活,它开始在LoadingComponent
的孩子处激活。实际上,当我在 reducer 处设置断点时,状态会发生变化......在 Redux Dev Tool 开始处于活动状态后,我可以观察到加载状态实际上已更改为 false -> true -> false。如果有人可以提供帮助,我将不胜感激。
【问题讨论】:
可以发一下收听loadCurrencies(currencies.rates)
的reducer吗?
通过connect()
将加载组件连接到商店的部分在哪里?
当你的空鱼被捕获时会发生什么?您应该删除整个 try/catch 包装器
【参考方案1】:
我建议将redux-logger
添加到您的商店:https://www.npmjs.com/package/redux-logger。这将有助于确定事件触发的顺序。
我最初的想法是,您可能在 loadCurrencies
和 loadingCurrencies
返回之间存在竞争条件。如果loadCurrencies
是一个promise,那么loadingCurrencies
应该在then
块中调度以表明promise 已经返回。
IMO 具有 bool arg 方法是一种代码味道,并且由于加载状态与实际加载方法相关联,因此将加载作为同一个减速器的一部分是有意义的。我通常遵循的模式是:
动作
export const getCurrencies = () =>
return dispatch =>
dispatch(requestCurrencies()) // loading: true
return api.getCurrencies()
.then(currencies => dispatch(receiveCurrencies(currencies)))
export const requestCurrencies = () => (
type: REQUEST_CURRENCIES,
loadingCurrencies: true
)
export const receiveCurrencies = currencies => (
type: RECEIVE_CURRENCIES,
currencies,
loadingCurrencies: false
)
【讨论】:
以上是关于Redux 调用 dispatch 函数但它不会改变 store的主要内容,如果未能解决你的问题,请参考以下文章
redux store dispatch 导致 React 中的 setState error()
使用 redux-thunk 和直接调用 dispatch() 有啥区别
如何测试 Redux 的 dispatch() 是不是已在 React Component (Jest + Enzyme) 中被调用