2017-04-04 96 views
5

我想在接收403錯誤時在axios攔截器中進行重定向。但是,我如何訪問React組件以外的歷史記錄?如何從axios攔截器重定向與反應路由器V4?

Navigating Programatically in React-Router v4,它在一個組件作出反應的情況下,但在這裏,我想在愛可信上下文

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

「歷史」的道具,此代碼試試:'進口{browserHistory}從「反應路由器」 ;'然後'browserHistory.push(「/ path」);' –

+0

嘗試從'react-router-dom'導入{browserHistory};然後'browserHistory.push(「/ path」)'並且它不工作,這是V3的方式,不是嗎? –

+0

是的不幸的是,這似乎不適用於V4路由器... –

回答

1

你試過渲染<Redirect>?這是使用v4重定向的標準方式。我不確定你的代碼在哪裏,但只要你導入了React,它就可以工作。

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

下面是<Redirect>

+2

'返回<重定向到='/ somePage'/>' 不適用於我 –

1

的文檔,我發現最好的解決辦法是定義我的主要反應的組分內axios.interceptors和使用that來處理錯誤: (以及withRouter從路由器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

我解決了這個問題,通過從組件樹外部訪問我的Redux Store,並從註銷按鈕發送同樣的動作,因爲我的攔截器是在一個單獨的文件並在加載任何Component之前加載。

所以,基本上,我做了以下內容:

index.js文件:

//....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')); 

,並在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); 
    }); 

    } 
}; 

最後,但並非最不重要的,我有一個HOC(高階組件),用於封裝受保護的組件,以便在會話結束時執行實際的重定向。這樣,當我觸發動作類型UNAUTH_USER時,它會將我的isLogged屬性設置爲我的session縮減器,以false,因此此組件會隨時得到通知併爲我執行重定向。

的文件require-auth.js組件:

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

希望幫助!

0

我使用的反應路由器-DOM,它具有能在過渡用於新航線

history.push('/newRoute')