React Native调用含自定义Hook的地理定位API报错求助
解决React Native中普通函数调用含Mobx状态的地理定位API问题
错误原因分析
- Invalid hook call:你在普通异步函数
getCoords里调用geolocationApi(),而该函数内部使用了useStore自定义Hook——Hook只能在函数组件或自定义Hook的顶层调用,违反规则导致报错。 - 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
相关产品推荐
相关产品推荐

