Redux和Axios在GET API请求上返回Promise对象

时间:2019-01-05 08:15:26

标签: javascript reactjs redux axios redux-thunk

我正在尝试通过向api发送get请求来获取数据,我正在获取数据,但是它在promise对象中,

我已经尝试了几种方法来解决此问题,但是我无法解决问题。

还原器:personal-detail-reducer.js

XML

组件:personal-detail.js

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">


    <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:ems="10"
            android:id="@+id/nameTxt" android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent" android:layout_marginRight="8dp" android:layout_marginStart="8dp"
            app:layout_constraintStart_toStartOf="parent" android:layout_marginLeft="8dp"
            app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="8dp" android:hint="Name"/>
</android.support.constraint.ConstraintLayout>

我已经配置了thunk

store.js

import Http from "../utils/Http";
import {PERSONAL_DETAIL} from "../constants/api";
import {GET_PERSONAL_DETAIL} from "../constants/personsal-detail-constants";

const initialState = {
    data: ''
};

const personalDetailReducer = (state = initialState, action) => {
    if(action.type === GET_PERSONAL_DETAIL){
        return (dispatch) => {
            return Http.get(PERSONAL_DETAIL).then(response => {
                return{
                    data: dispatch(response.data.data)
                };
            }).catch(error => {});
        }
    }
    return state;
};

export default personalDetailReducer;

请找到附件以供参考Here is the dispatch response in next state and console as well which is returning dispatch

2 个答案:

答案 0 :(得分:1)

状态为promise,因为reducer返回promise而不是解析的数据。为了满足您的要求,应该在异步操作完成并解析数据之后调用reducer。因此,您可能希望将HTTP请求从reducer移至动作创建者,并在解析数据后立即调度相应的动作。

通常,动作创建者会保存在单独的文件中,例如

personal-detail-actions.js

import Http from "../utils/Http";
import {PERSONAL_DETAIL} from "../constants/api";
import {GET_PERSONAL_DETAIL} from "../constants/personsal-detail-constants";

export const setPersonalDetail = payload => ({
  type: GET_PERSONAL_DETAIL,
  payload,
});

export const fetchPersonalDetail = () => dispatch => {
  return Http.get(PERSONAL_DETAIL).then(response => {
    return dispatch(setPersonalDetail(response.data.data));
  }).catch(e => {
    console.error(e);
  });
}

由于异步操作现在在动作创建者中被隔离,所以简化器得到简化:

personal-detail-reducer.js

import {GET_PERSONAL_DETAIL} from "../constants/personsal-detail-constants";


const initialState = {
  data: ''
};

const personalDetailReducer = (state = initialState, action) => {
  switch (action.type) {
    case GET_PERSONAL_DETAIL:
      return {
        ...state,
        data: action.payload
      };
    default:
      return state;
  }
};

export default personalDetailReducer;

最后要做的是使组件调用动作创建者(不要忘记将其导入到组件中):

personal-detail.js

const mapStateToProps = (state) => {
  return{
    state
  }
};
const mapDispatchToProps = (dispatch) => {
  return {
    onGetPersonalDetail: () => dispatch(fetchPersonalDetail())
  }
}
export default connect(mapStateToProps, mapDispatchToProps) (TutorPersonalDetail);

答案 1 :(得分:1)

我通常不将HTTP调用包含在我的reducer中。请记住,reducer都是同步调用,因此解决此问题的一种好方法是在重击操作中。这是一个示例:

/** Notice that those actions are private. not exported to the components */
const getPersonalDetailStart = () => {
  return {
    type: GET_PERSONAL_DETAIL_START
  };
};

const getPersonalDetailSuccess = (profile) => {
  return {
    type: GET_PERSONAL_DETAIL_SUCCESS,
    profile
  }
};

const getPersonalDetailFailure = (error) => {
  return {
    type: GET_PERSONAL_DETAIL_FAILURE,
    error
  };
};

/** Here is the thunk action that is available to components */
export const getPersonalDetail = () => (dispatch) => {
  // Fire start action to display a loading indicator for example
  dispatch(getPersonalDetailStart());
  // Return the promise the thunk middleware
  return BackendAPI.getPersonalDetail().then(
    // on success, fire successful action.
    response => dispatch(getPersonalDetailSuccess(response.data.profile)),
    // on failure, fire failure action to e.g. show error message to user
    error => dispatch(getPersonalDetailFailure(error))
  );
};

现在,在减速器上,只需以与发生同步操作相同的方式处理操作即可。

export const personalReducer = (state, action) => {

    switch (action.type) {
    case GET_PERSONAL_DETAIL_START:
        return {
            ...state,
            isLoading: true
        };
    case GET_PERSONAL_DETAIL_SUCCESS:
        return {
            ...state,
            isLoading: false,
            profile: action.profile
        };
    case GET_PERSONAL_DETAIL_FAILURE:
        return {
            ...state,
            isLoading: false,
            error: error
        };
    default:
      return state;
    }

}; 

组件中的演示如下:

import React, {Component, Fragment} from 'react';
import {bindActionCreators} from "redux";
import {connect} from 'react-redux';
import {getPersonalDetail} from './actions/your_actions';

export default class DemoComponent extends Component {

  componentDidMount() {
    const {getPersonalDetail} = this.props;
    getPersonalDetail();
  }

  render() {
    return <div>your html here</div>;
  }

}


const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({getPersonalDetail}, dispatch);
};


DemoComponent = connect(null, mapDispatchToProps)(DemoComponent);