简体   繁体   中英

Returning promise object on GET API request by Redux and Axios

I am trying to fetch data by sending get request to api, I am getting data but Its in the promise object,

I have tried in couple of techniques to resolve this issue, but I am unable to solve the problem.

Reducer: personal-detail-reducer.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;

Component: personal-detail.js

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

I have already configured thunk

store.js

import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk';
import {createLogger} from 'redux-logger';
import {rootReducer} from '../reducers/index';

const loggerMiddleware = createLogger();

export const store = createStore(
    rootReducer,
    applyMiddleware(
        thunkMiddleware,
        loggerMiddleware
    )
);

Please find the attachment for reference Here is the dispatch response in next state and console as well which is returning dispatch

There is a promise in state because the reducer returns a promise instead of a resolved data. To meet your requirement the reducer should be called after the async operation is done and data is resolved. Therefore, you may want to move the HTTP request out of reducer to an action creator and dispatch the corresponding action as soon as the data is resolved.

Usually action creators are kept in a separate file, eg

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

Since the async operation is now isolated in the action creator, the reducer gets simplified:

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;

The last thing to do is to make the component call the action creator (don't forget to import it into the component):

personal-detail.js

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

I usually don't include the HTTP calls in my reducers. Remember the reducers are all sync calls, so a good way to handle this is inside a thunk action. Here is an example:

/** 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))
  );
};

Now on your reducer, just handle the actions in the same way a sync action will occur.

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

}; 

A demonstration in component could be as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM