Redux Thunk - Async,使用Promises链接动作

时间:2016-10-18 12:52:26

标签: asynchronous redux react-redux redux-thunk axios

所以我在过去的两天里一直对这个问题感到难过。

所以在应用程序中,有多个组织。我还有一个允许用户在组织之间切换的操作。

组织减速机:

import {
    FETCH_ORGANIZATION_LIST_REQUEST,
    FETCH_ORGANIZATION_LIST_SUCCESS,
    ORGANIZATION_ERROR,
    PICK_ORGANIZATION } from '../actions/types'

const INITIAL_STATE = { error: null,  organizations: [],  isFetching: false, currentOrganization: null, hasCurrentOrganization: false };

export default function (state = INITIAL_STATE, action) {
    switch (action.type){
        case FETCH_ORGANIZATION_LIST_REQUEST:
            return { ...state, isFetching: action.isFetching, error: null};
        case FETCH_ORGANIZATION_LIST_SUCCESS:
            return { ...state, isFetching: action.isFetching, organizations: action.payload, error: null };
        case ORGANIZATION_ERROR:
            return { ...state, isFetching: action.isFetching, error: action.payload };
        case PICK_ORGANIZATION:
            return { ...state, currentOrganization: action.organizationId, hasCurrentOrganization: action.hasCurrentOrganization };
        default:
            return state
    }
}

获取组织和选择组织的电话如下:

export function fetchOrganizationList() {
    const url = `/organizations`;

    return (dispatch) => getData(
        FETCH_ORGANIZATION_LIST_REQUEST,
        FETCH_ORGANIZATION_LIST_SUCCESS,
        ORGANIZATION_ERROR,
        true,
        url,
        dispatch);
};

export function pickOrganization(organizationId) {
    return (dispatch) => {
        dispatch({
            type: PICK_ORGANIZATION,
            organizationId: organizationId,
            hasCurrentOrganization: true
        })
    }
};

我有一个getData调用,也用于其他服务器调用:

export function getData( actionRequest, actionSuccess, errorType, isAuthReq, url, dispatch) {
    const requestUrl = API_URL + url;
    let headers = {};

    dispatch({
        type: actionRequest,
        isFetching: true,
        error: null
    });

    if(isAuthReq) {
        headers = {headers: {'Authorization': 'Token ' + cookie.load('token')} }
    }

    axios.get(requestUrl, headers)
        .then((response) => {
            dispatch({
                type: actionSuccess,
                isFetching: false,
                payload: response.data
            });
            return response.data; 
        })
        .catch((error) => {
            errorHandler(dispatch, error, errorType)
        })

} 

最后我有一个OrganizationSelector.jsx容器组件,它允许我挑选当前的组织。

import React, {
    Component,
    PropTypes,
} from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import { fetchOrganizationList, pickOrganization, fetchAndPickCurrentOrganization } from '../../actions/organizations';

import Picker from '../../components/Picker';

class OrganizationSelector extends Component {


    componentDidMount() {

        this.props.fetchOrganizationList();
    }

    render() {
        const { isFetching, error, organizations, dispatch } = this.props;

        let count = !isFetching ? organizations.count : 1;

        return (
            <div>
                {isFetching && !error &&
                <li>Loading...</li>}
                {!isFetching && !error && count > 1 &&
                <Picker
                    currentOrganization={organizations.results[0].name}

                    options={organizations.results}
                    onSubmit={pickOrganization()}
                />
                }
                {!isFetching && !error && count === 1 &&
                <div>
                    {organizations.results[0].name}
                </div>
                }
            </div>
        );
    }
}

OrganizationSelector.propTypes = {};
OrganizationSelector.defaultProps = {};

const mapStateToProps = state => ({
    organizations: state.organization.organizations,
    isFetching: state.organization.isFetching,
    error: state.organization.error
});

function mapDispatchToProps(dispatch) {
    return {
        fetchOrganizationList: bindActionCreators(fetchOrganizationList, dispatch),
        // pickOrganization: bindActionCreators(pickOrganization, dispatch)
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(OrganizationSelector);

现在我遇到的问题是在同一个动作创建者中将动作链接在一起。我想在fetchOrganizationList动作完成提取后传递picOrganization动作,我尝试通过fetchListAndPickCurrentOrganization()函数做了很多事情。

export function fetchListAndPickCurrentOrganization() {
    return (dispatch) => {
        dispatch(fetchOrganizationList())
            .then(response => {
                console.log(response) // This is where the Pick organization call will go
            })
            .catch(() => {
                console.log('error')
            })
    }
};

我也尝试直接在fetchOrganizationList()调用中进行axios调用,但是我一直认为.then是未定义的,我猜测是因为来自axios调用的返回响应没有通过到.then。

我尝试过很多东西,但目标是在首次安装应用程序时运行这两个调用,当然会再次使用pickOrganization调用来切换组织。

1 个答案:

答案 0 :(得分:0)

所以解决方案非常简单,我不得不返回axios.get请求,因为它没有在我的初始解决方案中返回,这就是为什么没有传递给.then,并且它是未定义的。

export function getData( actionRequest, actionSuccess, errorType, isAuthReq, url, dispatch) {
    const requestUrl = API_URL + url;
    let headers = {};

    dispatch({
        type: actionRequest,
        isFetching: true,
        error: null
    });

    if(isAuthReq) {
        headers = {headers: {'Authorization': 'Token ' + cookie.load('token')} }
    }

    return axios.get(requestUrl, headers)
        .then((response) => {
            dispatch({
                type: actionSuccess,
                isFetching: false,
                payload: response.data
            });
            return response.data; 
        })
        .catch((error) => {
            errorHandler(dispatch, error, errorType)
        })

} 

谢谢@Ashley'CptLemming'Wilson为我解决这个问题。