【问题标题】:Redirect to View Component from an Axios interceptor (outside of a component) in React Native with React-Router-Native使用 React-Router-Native 在 React Native 中从 Axios 拦截器(组件外部)重定向到查看组件
【发布时间】:2020-03-20 07:45:47
【问题描述】:

我正在开发一个服务类来创建一个 Axios 实例(在 React Native 中),我正在使用一些拦截器来注入 JWT 令牌以针对 API 进行身份验证。

当应用检测到access token过期时,自动使用refresh token同时请求新令牌和新刷新令牌。

问题是刷新令牌由于不活动而过期。

我想在刷新令牌过期时将用户重定向到登录视图组件。

考虑到服务类是无状态的并且不关心它是从哪个组件调用的,我需要做什么才能重定向到我的登录视图组件?

这是我到现在为止的:


//API.js

import axios from 'axios';
import TokenStorage from './TokenStorage';

const API = axios.create({
    responseType: 'json',
});

...

API.interceptors.response.use((response) => {
    // Return a successful response back to the calling service
    return response;
}, (error) => {

    // Return any error which is not due to authentication back to the calling service
    ...

    // Logout user if token refresh didn't work or user is disabled
    if (error.config.url === '/tokens/refresh/' || error.response.data.code === 'access_invalid') {

        TokenStorage.cleanStorage();

        // TODO - Redirect to the "/login" route [Login View Component]

        return new Promise((resolve, reject) => {
            reject(error);
        });
    } else if (error.config.url === '/tokens/') {
        // Reject if user credentials are wrong
        return new Promise((resolve, reject) => {
            reject(error);
        });
    }

    // Try request again with new token
    ...

});

export default API;

环境:

"axios": "^0.19.0",
"react": "16.9.0",
"react-native": "0.61.2",
"react-router-native": "^5.1.2"

PS:这是一个与this 非常相似的问题,但我需要一个使用 React Router Native 的解决方案。

编辑 1:

我已经尝试使用"history": "^4.10.1" 包如下,但没有成功:


// API.js

import {createMemoryHistory} from 'history';

const history = createMemoryHistory();

...
// Logout user if token refresh didn't work or user is disabled
    if (error.config.url === '/tokens/refresh/' || error.response.data.code === 'access_invalid') {

        TokenStorage.cleanStorage();

        history.push('/login'); // This don't work!

        return new Promise((resolve, reject) => {
            reject(error);
        });
    } else if (error.config.url === '/tokens/') {
        // Reject if user credentials are wrong
        return new Promise((resolve, reject) => {
            reject(error);
        });
    }

【问题讨论】:

  • 你试过 redux 吗?
  • 从哪里调用 API.js 文件??
  • 通常来自类和函数组件。我大部分时间在 componentDidMount 方法中使用它来从外部 API 加载数据,以及从 API 进行某种获取/从 API 获取的相关函数。

标签: react-native redirect axios react-router-native


【解决方案1】:

没有 Redux

//EventPublisher.js    
export default class EventPublisher {
  static instance;
  listeners = {};

  constructor(validEvents){
    validEvents.forEach(ve=>{
      this.listeners[ve] = []
    })
  }

  subscribe(event, listener){
    if(!this.listeners[event]) throw 'Invalid event'
    this.listeners[event].push(listener)
    return ()=>{
      this.listeners[event].remove(listener)
    }
  }

  publish(event){
    this.listeners[event].forEach(l=>l())
  }
}

在您的顶级组件中

componentDidMount(){
  EventPublisher.instance = new EventPublisher([
    'REFRESH_TOKEN',
  ])
  this.cancelEventSubscription = EventPublisher.instance.subscribe('REFRESH_TOKEN', ()=>{
    //Logic of react router native to navigate to LoginScreen
  })
}
componentWillUnmount(){
  this.cancelEventSubscription()
}

在 axios 中

if (error.config.url === '/tokens/refresh/' || error.response.data.code === 'access_invalid') {

        TokenStorage.cleanStorage();

        // TODO - Redirect to the "/login" route [Login View Component]
        EventPublisher.instance.publish('REFRESH_TOKEN')

        return new Promise((resolve, reject) => {
            reject(error);
        });
    } else if (error.config.url === '/tokens/') {
        // Reject if user credentials are wrong
        return new Promise((resolve, reject) => {
            reject(error);
        });
    }

【讨论】:

  • 这是一种解决方法,我的建议是使用 redux
  • 我没有使用库进行状态管理。我需要保持简单。谢谢,我会检查答案,我会尽快给你反馈。
  • 您的解决方案就像一个魅力。不幸的是,赏金期已过,抱歉。至少我把它标记为正确答案。
  • 太好了,不用担心赏金,这将是另一个场合
猜你喜欢
  • 2019-06-11
  • 1970-01-01
  • 2017-08-29
  • 2021-12-25
  • 2018-10-14
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多