2017-04-04 28 views
5

Chcę dokonać przekierowania w przechwytywaczach osi podczas otrzymywania błędu 403. Ale w jaki sposób mogę uzyskać dostęp do historii poza składnikami React?Jak przekierować z urządzenia przechwytującego Axios za pomocą Routera V4?

W Navigating Programatically in React-Router v4, to w kontekście React Component, ale tutaj staram się w kontekście Axios

axios.interceptors.response.use(function (response) { 
    // Do something with response data 
    return response; 
    }, function (error) { 
    // Do something with response error 
    if(error.response.status === 403) { console.log("Redirection needed !"); } 

    // Trow errr again (may be need for some other catch) 
    return Promise.reject(error); 
}); 
+0

spróbuj tego kodu: 'import {browserHistory} z„reagować-Router” ; 'then' browserHistory.push ("/ path"); ' –

+0

Próbowano z' import {browserHistory} z 'react-router-dom'; 'then' browserHistory.push ("/ path") 'i to nie działa, to jest droga V3, czyż nie? –

+0

tak niestety to nie działa dla routera V4 ... –

Odpowiedz

1

Czy próbowałeś renderowania <Redirect>? Jest to standardowy sposób przekierowania za pomocą wersji v4. Nie wiem, gdzie jest twój kod, ale tak długo, jak jesteś zaimportowany React, powinien działać.

axios.interceptors.response.use(function (response) { 
    return response; 
    }, function (error) { 
    // Do something with response error 
    if(error.response.status === 403) { 
     return <Redirect to='/somePage' /> 
    } 

    // Trow errr again (may be need for some other catch) 
    return Promise.reject(error); 
}); 

Oto dokumentacja <Redirect>

+2

'return ' Nie działa dla mnie –

1

Najlepszym rozwiązaniem znalazłem jest zdefiniowanie axios.interceptors wewnątrz moich głównych składników reagować i wykorzystywać that do obsługi błędów: (iz withRouter od routera V4)

import {withRouter} from 'react-router-dom'; 

class Homepage extends Component { 
    static propTypes = { 
    history: PropTypes.object.isRequired 
    } 

    constructor(props){ 
    super(props); 

    let that = this; 
    axios.interceptors.response.use(function (response) { 
     // Do something with response data 
     return response; 
     }, function (error) { 
     // Do something with response error 
     if(error.response.status === 403) { that.handle403() } 

     // Trow errr again (may be need for some other catch) 
     return Promise.reject(error); 
    }); 

    } 

    handle403(){ 
    this.props.history.push('/login'); 
    } 
7

Rozwiązałem to, uzyskując dostęp do mojego sklepu Redux spoza drzewa komponentów i wysyłając mu tę samą akcję z przycisku wylogowania, ponieważ moje przechwytujące są tworzone w oddzielony plik i ładowany przed załadowaniem jakiegokolwiek komponentu.

Więc w zasadzie, zrobiłem co następuje:

Na index.js pliku:

//....lots of imports ommited for brevity 
import { createStore, applyMiddleware } from 'redux'; 
import reduxThunk from 'redux-thunk'; 
import reducers from './reducers'; 
import { UNAUTH_USER } from './actions/types'; //this is just a constants file for action types. 

const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore); 
const store = createStoreWithMiddleware(reducers); 

//Here is the guy where I set up the interceptors! 
NetworkService.setupInterceptors(store); 

//lots of code ommited again... 
//Please pay attention to the "RequireAuth" below, we'll talk about it later 

ReactDOM.render(
    <Provider store={store}> 
     <BrowserRouter> 
      <div> 
       <Header /> 
       <main className="plan-container"> 
        <Switch> 
         <Route exact path="/" component={Landing} /> 
         <Route exact path="/login" component={Login} /> 
         <Route exact path="/signup" component={Signup} /> 
         <Route exact path="/calendar" component={RequireAuth(Calendar)} /> 
         <Route exact path="/profile" component={RequireAuth(Profile)} /> 
        </Switch> 
       </main> 
      </div> 
     </BrowserRouter> 
    </Provider> 
    , document.querySelector('.main-container')); 

A w pliku network-service.js:

import axios  from 'axios'; 
import { UNAUTH_USER } from '../actions/types'; 

export default { 
    setupInterceptors: (store) => { 

    // Add a response interceptor 
    axios.interceptors.response.use(function (response) { 
     return response; 
    }, function (error) { 
     //catches if the session ended! 
     if (error.response.data.token.KEY == 'ERR_EXPIRED_TOKEN') { 
      console.log("EXPIRED TOKEN!"); 
      localStorage.clear(); 
      store.dispatch({ type: UNAUTH_USER }); 
     } 
     return Promise.reject(error); 
    }); 

    } 
}; 

Last but not least, mam HOC (Higher Order Component), który zawijam chronione komponenty w miejscu, w którym wykonuję rzeczywiste przekierowanie, gdy sesja się kończy. W ten sposób po wywołaniu typu akcji UNAUTH_USER ustawia on moją właściwość isLogged na moim reduktorze session na false i dlatego ten komponent otrzymuje powiadomienie i wykonuje przekierowanie w dowolnym czasie.

Plik do require-auth.js komponentu:

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

export default function(ComposedComponent) { 

    class RequireAuth extends Component { 

     componentWillMount() { 
      if(!this.props.session.isLogged) { 
       this.props.history.push('/login'); 
      } 
     }; 

     componentWillUpdate(nextProps) { 
      if(!nextProps.session.isLogged) { 
       this.props.history.push('/login'); 
      } 
     }; 

     render() { 
      return <ComposedComponent {...this.props} /> 
     } 
    } 

    function mapStateToProps(state) { 
     return { session: state.session }; 
    } 

    return connect(mapStateToProps)(RequireAuth); 
} 

nadzieję, że pomoże!

0

Używam reagować-Router-dom i ma „Historia” rekwizyty, które mogą być stosowane w okresie przejściowym do nowej trasy

history.push('/newRoute') 
Powiązane problemy