You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native调用含自定义Hook的地理定位API报错求助

解决React Native中普通函数调用含Mobx状态的地理定位API问题

错误原因分析

  1. Invalid hook call:你在普通异步函数getCoords里调用geolocationApi(),而该函数内部使用了useStore自定义Hook——Hook只能在函数组件或自定义Hook的顶层调用,违反规则导致报错。
  2. geolocationApi.default.requestLocationPermissions is not a function:改成export const geolocationApi后,你依然用默认导入import geolocationApi from...,但默认导出不存在,所以找不到对应方法。

解决方案:剥离Hook依赖,重构API为纯异步函数

步骤1:直接导入Mobx Root Store实例

找到你的Mobx根Store创建文件(比如@stores/rootStore.js),确保它导出了全局唯一的Store实例:

// @stores/rootStore.js
import { makeAutoObservable } from "mobx";
import MapStore from "./mapStore";

class RootStore {
  constructor() {
    this.mapStore = new MapStore(this);
    makeAutoObservable(this);
  }
}

const rootStore = new RootStore();
export default rootStore;

步骤2:重构geolocationApi文件

去掉useStoreHook,直接导入根Store,将API封装为纯对象方法:

import _ from 'lodash';
import Geolocation from 'react-native-geolocation-service';
import rootStore from '@stores/rootStore'; // 直接导入全局Store实例

const geolocationApi = {
  // 请求定位权限并获取坐标
  requestLocationPermissions: async (getCityName = false) => {
    const auth = await Geolocation.requestAuthorization("whenInUse");
    if (auth === "granted") {
      rootStore.mapStore.setLocationEnabled(true);
      const coords = await geolocationApi.getMe(getCityName);
      return coords;
    } else {
      rootStore.mapStore.setLocationEnabled(false);
    }
  },

  // 获取当前位置(包装为Promise支持await)
  getMe: async (getCityName = false) => {
    return new Promise((resolve, reject) => {
      Geolocation.getCurrentPosition(
        async (position) => {
          const results = await geolocationApi.onSuccess(position.coords, getCityName);
          resolve(results);
        },
        (error) => {
          console.log(error.code, error.message);
          reject(error);
        },
        { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
      );
    });
  },

  // 处理定位成功逻辑
  onSuccess: async (coords, getCityName) => {
    let result = { coords };
    if (getCityName) {
      // 这里添加获取城市名的逻辑
      // result.cityName = await fetchCityName(coords.latitude, coords.longitude);
    }
    return result;
  }
};

export default geolocationApi;

步骤3:组件中直接调用

现在可以按你期望的方式简单调用:

import geolocationApi from '@utils/geolocationApi.js'

const getCoords = async () => {
  try {
    const result = await geolocationApi.requestLocationPermissions(true);
    console.log('定位结果:', result);
  } catch (error) {
    console.error('定位失败:', error);
  }
};

可选灵活方案:传递Store实例

如果不想依赖全局Store,也可以将Store作为参数传入API:

// geolocationApi.js
const geolocationApi = (store) => ({
  requestLocationPermissions: async (getCityName = false) => {
    const auth = await Geolocation.requestAuthorization("whenInUse");
    if (auth === "granted") {
      store.mapStore.setLocationEnabled(true);
      const coords = await geolocationApi(store).getMe(getCityName);
      return coords;
    } else {
      store.mapStore.setLocationEnabled(false);
    }
  },
  // 其他方法同上,替换rootStore为store参数
});

export default geolocationApi;

组件中调用:

import geolocationApi from '@utils/geolocationApi.js';
import { useStore } from '@hooks/use-store';

const MyComponent = () => {
  const rootStore = useStore();
  const api = geolocationApi(rootStore);

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

  return <View>...</View>;
};

内容的提问来源于stack exchange,提问作者gabogabans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:20:43