Перехватывать все запросы API с помощью компонента Loader - React Axios - PullRequest
0 голосов
/ 28 февраля 2019

Я хотел бы добавить компонент Loader, который будет отображаться при каждом вызове API в React.У меня есть флаг isFetching в моем редукторе, и теперь я могу сделать это на уровне компонентов на основе этого реквизита.Но мне нужен глобально.Есть ли способ достичь этого?

Это реализация , которую я планирую использовать.

Ниже приведен мой dataService:

        //if dev mode them URL prefix = http://127.0.0.1:8080/
    //else
    // prefix= .

    // url= prefix + /users/xyz
    import axios from 'axios';

    const DEV_MODE_URL_PREFIX = '/api/';
    const PROD_MODE_URL_PREFIX = './api/';
    const ENV = process.env.NODE_ENV;

    function getService(relativeUrl, options) {

        return dataService(relativeUrl, options);
    }

    function postService(relativeUrl, dataToPost, options) {
        return dataService(relativeUrl, options, dataToPost);
    }

    function dataService(relativeUrl, options, dataToPost) {
        /**
         * dataToPost = {
         *  key: value
         * } || string
         * options = {
         *  actions: {
         *    requestAction: function ()
         *    successAction: function (response)
         *    failureAction: function (error)
         *  },
         *  shouldRequest: function (state)
         * }
         */
        return (dispatch, getState) => {
            let url;
            const { requestAction, successAction, failureAction } = options.actions;
            if (relativeUrl.match(/json/)) {
                url = relativeUrl;
            } else {
                if (relativeUrl[0] === '/') {
                    relativeUrl = relativeUrl.slice(1);
                }
                if (relativeUrl[relativeUrl.length - 1] !== '/') {
                    relativeUrl += '/';
                }
                if (ENV !== 'production') {
                    url = DEV_MODE_URL_PREFIX + relativeUrl;
                } else {
                    url = PROD_MODE_URL_PREFIX + relativeUrl;
                }
            }

            if (options.shouldRequest(getState())) {
                let promise;
                const data = typeof dataToPost === 'string' ? { 'data': dataToPost } : dataToPost;
                dispatch(requestAction());
                promise = dataToPost ? axios.post(url, data, { withCredentials: true }) : axios.get(url, { withCredentials: true });
                return promise
                    .then(response => {
                        console.log(
                            `status: ${response.status}
                message: ${response.message}`
                        );
                        if (response.status === 200) {
                            return dispatch(successAction(response, dispatch));
                        }
                        return Promise.reject(response);
                    })
                    .catch(error => {
                        console.log(error);
                        return dispatch(failureAction(error));
                    });
            } else {
                return Promise.reject('FETCHING');
            }
        };
    }

    export {
        getService,
        postService
    };

Пожалуйста, совет.

Я сделал это в Earlir в Angular и хотел бы то же самое в React.

1 Ответ

0 голосов
/ 01 марта 2019

Вы можете установить axios перехватчики в компоненте более высокого уровня, скажем, в App.Вы можете определить состояние загрузки в редукторе с помощью типов действий "SHOW_LOADER" и "HIDE_LOADER".Эти перехватчики будут отправлять соответствующие действия до того, как запрос будет отправлен и получен через axios , обновляя состояние загрузки в хранилище, через которое вы можете отобразить компонент Loader.

Надеюсь, что это ответ на ваш вопрос.

Компонент приложения

import React from 'react';
import axios from 'axios'
import { connect } from 'react-redux';
import { loading } from '../actions'
import Loader from './Loader'

class App extends React.Component{
 componentWillMount(){
   const self = this
   axios.interceptors.request.use(function (config) {
     // spinning start to show
     self.props.loading(true)
     return config
    }, function (error) {
      return Promise.reject(error);
    });

    axios.interceptors.response.use(function (response) {
     // spinning hide
      self.props.loading(false)

     return response;
   }, function (error) {
     return Promise.reject(error);
   });
 }
 render(){
   return (
    <div>
      { this.props.loader ? <Loader /> : null }

      {/* 
        Your other components
      */}
    </div>
   )
 }

}

const mapStateToProps = (state)=>{
  return {
    loader: state.loader
  }
}

export default connect(mapStateToProps,{
  loading
})(App);

Редуктор загрузчика

const loader = (state = false, action) => {
    switch (action.type) {
        case "SHOW_LOADER":
            return action.data;
            break;
        case "HIDE_LOADER":
            return action.data;
            break;
        default:
            return state;
    }
}

export default loader;

Действие

export const loading = (bool)=>{
  return bool ? {
    type:"SHOW_LOADER",
    data:bool
  }: {
    type: "HIDE_LOADER",
    data: bool
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...