Home > other >  Importing async function error: Invalid hook call. Hooks can only be called inside of the body of a
Importing async function error: Invalid hook call. Hooks can only be called inside of the body of a

Time:10-05

All I wanna do is be able to call logic from my geolocationApi file into my react-native components whenever I want, NOT LIKE A HOOK but normal async functions, I'm using a custom hook in the geolocationApi file I'm importing though! (custom hooks handles mobx state updates)

I want to call it like this in my functional components (plain and easy):

import geolocationApi from '@utils/geolocationApi.js'

const getCoords = async () =>
{
    let result = await geolocationApi().requestLocationPermissions(true);
};

My geolocationApi file where I have a bunch of functions about geolocation I don't want to crowd my components with.

@utils/geolocationApi.js

import _ from 'lodash';
import Geolocation from 'react-native-geolocation-service';
import { useStore } from '@hooks/use-store';


const geolocationApi = () => {

    //Custom hook that handles mobx stores
    const root = useStore();
        

    const requestLocationPermissions = async (getCityName = false) =>
    {
        const auth = await Geolocation.requestAuthorization("whenInUse");
        if(auth === "granted")
        {
            root.mapStore.setLocationEnabled(true);
            let coords = await getMe(getCityName);
            return coords;
        }
        else
        {
            root.mapStore.setLocationEnabled(false);
        }
    };

    const getMe = async () =>
    {
        Geolocation.getCurrentPosition(
            async (position) => {
              let results = await onSuccess(position.coords);
              return results;
            },
            (error) => {
              console.log(error.code, error.message);
            },
            { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
        );
    };

      
    /*const onSuccess = async () => {}*/

    };
    
    export default geolocationApi;

This can't be that hard!

If I remove export default geolocationApi and instead add export const geolocationApi at the top I get:

geolocationApi.default.requestLocationPermissions is not a function

CodePudding user response:

You cannot use hooks outside React components. You can pass down the state to your function

import geolocationApi from '@utils/geolocationApi.js'

const getCoords = async (root) =>
{
    let result = await geolocationApi(root).requestLocationPermissions(true);
};

Then instead of using useStore()

import _ from 'lodash';
import Geolocation from 'react-native-geolocation-service';
import { useStore } from '@hooks/use-store';

// pass the root from top
const geolocationApi = (root) => {
   
  // your logic

  return {
    requestLocationPermissions,
    getMe
  }
}

Then somewhere in your component tree, ( an example with useEffect )

import getCoords from 'path'

const MyComp = () => {
  const root = useStore();

  useEffect(() => {
    getCoords(root)
  }, [root])
}

CodePudding user response:

As you said, geolocationApi is a regular function, not a React component/hook. So, it isn't inside the React lifecycle to handle hooks inside of it.

You can use the Dependency Injection concept to fix it.

Make geolocationApi clearly dependent on your store.

const geolocationApi = (store) => {

Then you pass the store instance to it.


const getCoords = async (store) =>
{
    let result = await geolocationApi(store).requestLocationPermissions(true);
};

Whoever React component calls the getCoords can pass the store to it.

//...
const root = useStore();
getCoords(root);
//...
  • Related