2

I'm building a code to check if access_token or refresh_token are valid. I'm using axios interceptors to check the response to generate new token.

How to use navigate(React Navigation) inside axios interceptors?

Error:

09:53:55.852 client_log FarmsList:React.FC -> error [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons

     axios.interceptors.response.use(
          (response) => {
            return response
          },
          async (error) => {
            const navigation = useNavigation()
            const originalRequest = error.config
            const accessToken = await getAccessToken()
            const refreshToken = await getRefreshToken()
        if (
          error.response.status === 400 &&
          originalRequest.url === connectTokenUrl &&
          accessToken
        ) {
          removeConnectToken()
          navigation.navigate('SignIn')
          return Promise.reject(error)
        }
    
        if (error.response.status === 401 && !originalRequest._retry) {
          originalRequest._retry = true
          console.log('entrou 401')
          if (!refreshToken) {
            navigation.navigate('SignIn')
            return Promise.reject(error)
          }
    
          const data = {
            grant_type: 'refresh_token',
            client_id: 'xxx',
            refresh_token: refreshToken,
          }
          const formData = new FormData()
          _.forEach(data, (value, key) => {
            formData.append(key, value)
          })
    
          return axios({
            method: 'post',
            url: connectTokenUrl,
            data: formData,
            headers: {'Content-Type': 'multipart/form-data'},
          }).then((response) => {
            const {access_token, refresh_token} = response.data
            connectToken(access_token, refresh_token)
            axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`
            return axios(originalRequest)
          })
        }
        return Promise.reject(error)
      },
    )
1

3 Answers 3

3

There are several ways to access the navigation props outside the navigation.

  1. The useNavigation hook : this is used for scenarios where you access the navigation prop from functional components which are under the navigation container. Eg : A navigation button which is inside a screen.

  2. The navigationRef : this is used for scenarios where you access the navigation outside the navigation, used for scenarios like redux middleware.

You should use the navgation ref for this scenario and perform your navigation actions. You can use the RootNavigation.js and call the navigation actions.

import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';

export default function App() {
  return (
    <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
  );
}

RootNavigation.js

import * as React from 'react';

export const navigationRef = React.createRef();

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}

Usage

import * as RootNavigation from '../../RootNavigation';

RootNavigation.navigate('ChatScreen', { userName: 'Lucy' });
Sign up to request clarification or add additional context in comments.

Comments

1

First you have to create a createNavigationContainerRef and a navigate function like this:

// RootNavigation.js

import { createNavigationContainerRef } from '@react-navigation/native';

export const navigationRef = createNavigationContainerRef()

export function navigate(name, params) {
  if (navigationRef.isReady()) {
    navigationRef.navigate(name, params);
  }
} 

Then add the newly created navigationRef to the NavigationContainer wrapper:

import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';

export default function App() {
  return (
    <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
  );
} 

You can now import the navigate function to any .js file and use it. Hope this was useful. For further reference, refer this article.

Comments

0

where is your navigation param? if you can show me more of your code (your full component) will be helpful, its possible that you are calling some hook outside of your functional component

3 Comments

I don't have any param
so how are you calling 'navigation.navigate('SignIn')' without having params? you need to pass the navigation param to your component or you can import {withNavigation} from 'react-navigation'; to use it
I notice you are using useNavigationHook, but you are using it in your Axios interceptor, you need to declare it at the top of your functional component to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.