How to use navigation in this function from importing a hook within this function? any idea?

Viewed 287

I am using a function to call an api and i have added navigation on 401 and i want to use navigation here. But as the hooks can be called from the component only. So anybody can tell me how can i add navigation here. So someone i can import here and use while passing in the function.

const GetApiRequestWithToken = async (url, params, headers) => {
    return new Promise((resolve, reject) => {
        axios.get(base_url_address + url, { headers: headers }).then(resp => {
            if (resp.status == 401) {
                UnAuthorizedLogout()
            } else {
                resolve(resp)
            }
        }).catch((error) => {
            resolve(error.response)
        });
    })
}

So this is a function and how can i import navigation in this. from hooks or some other way.

As this is not allowing to import here

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

and i don't want that everytime, i call GetApiRequestWithToken then pass navigation to it.

2 Answers

You can use a navigation provider pattern to achieve this. You can create a utility file like the following:

// util/navigation.js
import React from 'react';

export const navigationRef = React.createRef();

export const navigate = (routeName, params) => {
  navigationRef.current?.navigate(routeName, params);
};

This stores the navigator reference in a local variable. You can see that it requires the navigator object to be passed in by an external component. I would recommend calling this function in your top-level navigation stack component. You most likely already have a component that looks something like the below:

// NavigationContainer.js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from 'util/navigation';  // from util
import ExampleStack from './ExampleStack';

const Stack = createStackNavigator();

export default () => {
    return (
        <NavigationContainer ref={navigationRef}>  {/* store ref */}
            <Stack.Navigator
                initialRouteName="Example"
                ...
            >
                <Stack.Screen
                    name="Example"
                    component={ExampleStack}
                />
            </Stack.Navigator>
        </NavigationContainer>
    );
};

You can see here that the component created by createNavigationContainer will pass the ref to your navigation provider util above.

Finally, you can use the NavigationContainer created in this second file inside your App.js.

// App.js
import NavigationContainer from './NavigationContainer';


export default () => (
  <NavigationContainer />
);

Any other functions of the navigator can be added to navigationUtil.js now, for example goBack. You can now use the utility in your axios request like so:

// axios util
import { navigate } from './navigationUtil.js'; // new

const GetApiRequestWithToken = async (url, params, headers) => {
    return new Promise((resolve, reject) => {
        axios.get(base_url_address + url, { headers: headers }).then(resp => {
            if (resp.status == 401) {
                navigate('UnauthorizedLogoutScreen');  // new
                UnAuthorizedLogout();
            } else {
                resolve(resp)
            }
        }).catch((error) => {
            resolve(error.response)
        });
    })
}

I hope this is clear, feel free to ask if something has not been covered.

I think this can be done using a custom hook.

import React, { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';
import axios from 'axios';

export default function useFetchAPI(url, params, headers) {
    const [result, setResult] = React.useState(null);
    const navigation = useNavigation();
    useEffect(() => {
        axios
            .get(base_url_address + url, { headers: headers })
            .then((resp) => {
                console.log('resp: ', resp);
                if (resp.status == 401) {
                    // this will navigate to your UnAuthorizedLogout page
                    navigation.navigate('UnAuthorizedLogout');
                } else {
                    // otherwise, set the response to result state
                    setResult(resp);
                }
            })
            .catch((error) => {
                setResult(error.response);
            });
    }, [url])

    return result;
}

Related