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;
  
;

问题是loadingUserloadingCurrencies 总是错误的。这是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。这将有助于确定事件触发的顺序。

我最初的想法是,您可能在 loadCurrenciesloadingCurrencies 返回之间存在竞争条件。如果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 商店

redux store dispatch 导致 React 中的 setState error()

使用 redux-thunk 和直接调用 dispatch() 有啥区别

Redux - 调用一系列函数或reducer?

Redux-thunk - dispatch 不是一个函数

如何测试 Redux 的 dispatch() 是不是已在 React Component (Jest + Enzyme) 中被调用