Redux调用dispach函数,但它不会更改存储

时间:2017-11-25 20:41:22

标签: reactjs redux react-router react-redux

我正在编写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
    )
}

以下是我将stateprops

相关联的位置
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函数,当数据开始下载时以及在调度为false之后调度为true:

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)的缩减函数:

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 Dev Tool未激活,它开始在LoadingComponent个孩子处于活动状态。实际上,当我在reducer处设置断点时状态发生变化......在Redux Dev Tool开始激活之后,我可以观察到加载状态实际上已被改变为false - &gt;是的 - &gt;假。如果有人可以提供帮助,我将非常感激。

1 个答案:

答案 0 :(得分:1)

我建议您在商店中添加redux-loggerhttps://www.npmjs.com/package/redux-logger。这将有助于确定触发事件的顺序。

我最初的想法是,您可能会在loadCurrenciesloadingCurrencies之间返回竞争条件。如果loadCurrencies是一个承诺,那么loadingCurrencies应该在then块中发送,以表明承诺已经返回。

具有bool arg方法的IMO是一种代码气味,并且由于加载状态与实际加载方法有关,因此将加载作为同一个reducer的一部分是有意义的。我通常遵循的模式是:

行动

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
})