如何在使用拦截器时在 React Native 中导航登录

问题描述 投票:0回答:1

我正在使用 React Native 和 TypeScript

我想在拦截器部分强制导航到登录页面。但是,当我使用useNavigator时,遇到以下错误:

Error: Invalid hook call. Hooks can only be called inside of the body of a function 

如何导航到此处登录?

export const axiosApi = axios.create({
  baseURL,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
});

export const logoutUser = async () => {
  try {
    await AsyncStorage.clear();
    // when u use here to useNavigator : then 
    // Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
    // How can I navigate to login here??
    // .navigate('Login');
    
    console.log('logout success then u have to move page to login ');
  } catch (error) {
    console.log('logout failed', error);
  }
};`

完整代码在这里

import axios, {AxiosError, AxiosRequestConfig, AxiosResponse} from 'axios';
import localStorage from '../libs/async-storage';
import {TokenKeys} from '../libs/async-storage/constants/keys';
import {constSelector, useSetRecoilState} from 'recoil';
import {authState} from '../libs/recoil/states/auth';
import queryClient from './queryClient';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {navigate} from '../utils/navigationService';
import useNavigator from '../navigators/hooks/useNavigator';

export const baseURL = 'https://api.s-keep.site';

export const axiosApi = axios.create({
  baseURL,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
});

export const logoutUser = async () => {
  try {
    await AsyncStorage.clear();
    // when u use here to useNavigator : then 
    // Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
    // How can I navigate to login here??
    // .navigate('Login');
    
    console.log('logout success then u have to move page to login ');
  } catch (error) {
    console.log('logout failed', error);
  }
};
/**
 *  헤더 토큰 추가
 */
axiosApi.interceptors.request.use(
  async config => {
    const accessToken: string = await localStorage.get(TokenKeys.AccessToken);
    if (accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`;
    }
    return config;
  },
  error => Promise.reject(error),
);

/**
 *  Response Interceptor (응답 인터셉터)
 *  1. onFulfilled
 *  2. onRejected
 */
const onFulfilled = (res: AxiosResponse) => {
  return res;
};

let isRefreshing = false;
let failedQueue: any[] = [];

const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });

  failedQueue = [];
};

const onRejected = async (error: AxiosError) => {
  const originalConfig = error.config;

  if (error.response?.status === 500) {
    // I want this make the page move to login TT
    logoutUser();
    return Promise.reject(error);
  }

  if (originalConfig && error.response?.status === 401) {
    if (!isRefreshing) {
      isRefreshing = true;

      try {
        const refreshToken = await localStorage.get(TokenKeys.RefreshToken);
        const response = await axiosApi.post('/api/auth/jwt/reissue', {
          refreshToken,
        });

        if (response.status !== 200) {
          throw new Error(`Unexpected status code: ${response.status}`);
        }
        const result = response.data.result;
   
        await localStorage.set(TokenKeys.AccessToken, result.accessToken);
        const acc: string = await localStorage.get(TokenKeys.AccessToken);
       
        axiosApi.defaults.headers.common['Authorization'] = `Bearer ${acc}`;
        originalConfig.headers.Authorization = `Bearer ${acc}`;

        processQueue(null, result.accessToken);

        return axiosApi(originalConfig);
      } catch (err: unknown) {
        if (err instanceof AxiosError) {
          console.log('현재 발생한 오류는 ', err);
        } else {
          console.error('예상치 못한 오류 발생:', err);
        }
      } finally {
        console.log('finally 블록 실행');
        isRefreshing = false;
        //logoutUser();
      }
    } else {
      console.log(
        '401 error : 요청이 실패했습니다. 리프레시 토큰이 이미 갱신 중입니다.',
        error,
      );

      return new Promise(function (resolve, reject) {
        
        failedQueue.push({resolve, reject});
      })
        .then(token => {
          console.log('shit2');
          originalConfig.headers.Authorization = 'Bearer ' + token;
          return axiosApi(originalConfig);
        })
        .catch(err => {
          console.log('shit3 에러는 : ', err);
          return Promise.reject(err);
        });
    }
  }

  return Promise.reject(error);
};

axiosApi.interceptors.response.use(onFulfilled, onRejected);
typescript react-native
1个回答
0
投票

如果您想在组件生命周期之外调用导航,您需要将导航器引用添加到导航容器。但通常建议对组件内的状态更改或功能结果做出反应并以这种方式导航。

© www.soinside.com 2019 - 2024. All rights reserved.