如何使用 React Router V4 从 axios 拦截器重定向?

新手上路,请多包涵

我想在收到 403 错误时在 axios 拦截器中进行重定向。但是我怎样才能访问 React 组件之外的历史记录呢?

Navigating Programatically in React-Router v4 中,它在 React 组件的上下文中,但这里我在 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);
});

原文由 hilderic sb 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 866
2 个回答

我通过从组件树外部访问我的 Redux Store 并从注销按钮向它发送我的相同操作来解决这个问题,因为我的拦截器是在一个单独的文件中创建并在加载任何组件之前加载的。

所以,基本上,我做了以下事情:

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

希望有帮助!

原文由 DccBr 发布,翻译遵循 CC BY-SA 3.0 许可协议

我通过从 history ( https://github.com/ReactTraining/history ) 包创建浏览器历史并将其传递到拦截器函数然后调用 .push() 方法来解决这个任务.

主文件代码(部分):

 // app.js
import { createBrowserHistory } from 'history';
import httpService from './api_client/interceptors';

...

const history = createBrowserHistory();
httpService.setupInterceptors(store, history);

拦截器配置:

 import axios from 'axios';

export default {
  setupInterceptors: (store, history) => {

      axios.interceptors.response.use(response => {
        return response;
      }, error => {

      if (error.response.status === 401) {
        store.dispatch(logoutUser());
      }

      if (error.response.status === 404) {
         history.push('/not-found');
      }

      return Promise.reject(error);
    });
  },
};

此外,您应该使用 Router 来自 react-router ( https://github.com/ReactTraining/react-router ) 并传递与 history 相同的历史对象.

 // app.js
...
ReactDOM.render(
  <Provider store={store}>
     <Router history={history}>
        ...
     </Router>
  </Provider>
, document.getElementById('#root'))

原文由 Denys Kotsur 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进