我当前遇到一个问题,即挂钩返回的值意外未定义,而不是预期值。虽然 useGpsLocation Hook 中的日志记录表明正在设置正确的值,但实际的返回值似乎未定义。我认为这与异步的工作方式有关。
为了进一步详细说明,我尝试调用另一个文件中的 requestLocationPermissions 函数,特别是在 UserProvider 中。接下来,我的目标是将变量分配给 useGpsLocation 的返回值,这样我就可以在数据库中添加值。
使用GPS定位挂钩:
import React, { useEffect, useState } from 'react';
import { Text, Button, Platform, PermissionsAndroid } from 'react-native';
import Geolocation from 'react-native-geolocation-service';
import h3 from 'h3-js';
import moment from 'moment-timezone';
type Location = {
lat: number;
lng: number;
};
const useGpsLocation = () => {
const [gpsLocation, setGpsLocation] = useState<Location | null>(null);
const [error, setError] = useState<string | null>(null);
const [showInputs, setShowInputs] = useState(false);
const [timeZone, setTimeZone] = useState('' as string);
const requestLocationPermissions = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Allow Location',
message:
'Do you accept that you are sharing your location ' +
'We dont use your specific location',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
await getLocation();
} else {
setError('Location permission denied');
}
} catch (err) {
console.warn(err);
}
};
const getTimeZone = (latitude: number, longitude: number) => {
const timezone = moment.tz.guess();
setTimeZone(timezone);
};
const getLocation = async () => {
Geolocation.getCurrentPosition(
position => {
const { latitude, longitude } = position.coords;
setShowInputs(true);
const latLngToCell = h3.latLngToCell(latitude, longitude, 6);
const location = h3.cellToLatLng(latLngToCell);
getTimeZone(latitude, longitude);
setGpsLocation({ lat: location[0], lng: location[1] });
},
error => console.log("The location could not be loaded because ", error.message),
{ enableHighAccuracy: false, timeout: 20000 }
);
};
return { gpsLocation, error, showInputs, requestLocationPermissions, getLocation, timeZone, };
};
export default useGpsLocation;
用户提供程序文件
export default function UserProvider({ children }: PropsWithChildren<unknown>) {
const { user, isAuthed, isLoading, refetch } = useUser();
const { mutateAsync: activateAccount } = useActivateAccount();
const { t } = useTranslation();
const navigation = useNavigation<NavigationProp<HomeStackParamList>>();
const { gpsLocation, timeZone, requestLocationPermissions } = useGpsLocation();
useDynamicLinks(async link => {
try {
const url = new URL(link.url);
const urlParams = new URLSearchParams(url.search);
const accountToken = urlParams.get("prod_token") || urlParams.get("test_token");
if (!accountToken) {
throw new Error();
}
await requestLocationPermissions();
const latitude = gpsLocation?.lat;
const longtitude = gpsLocation?.lng;
const tz_name = timeZone;
console.log(latitude + " " + longtitude + tz_name);
Burnt.alert({
title: t("providers.user_provider.activate.title"),
message: t("providers.user_provider.activate.message"),
preset: "spinner",
duration: 10,
});
// ActivateAccount and add values in database
const { authorization_token } = await activateAccount({ accountToken, latitude, longtitude, tz_name });
Burnt.dismissAllAlerts();
Burnt.alert({
title: t("providers.user_provider.activate_success.title"),
message: t("providers.user_provider.activate_success.message"),
preset: "done",
});
await setAuthToken(authorization_token);
await refetch();
navigation.navigate("HomeScreen");
} catch (err) {
Burnt.dismissAllAlerts();
const alertData = {
title: t("providers.user_provider.activate_error.title"),
message: `${t("providers.user_provider.activate_error.message")}${err ? `\n\n${err}` : ""}`,
};
if (Platform.OS === "android") {
Alert.alert(alertData.title, alertData.message);
} else {
Burnt.alert({
title: alertData.title,
message: alertData.message,
preset: "error",
duration: 4,
});
}
}
});
return <UserContext.Provider value={{ user, isAuthed, isLoading, refetch }}>{children}</UserContext.Provider>;
}
上面的纬度、经度和 tz_name 值给了我未定义的值。
有人知道修复方法吗?
状态正在异步改变。使用 useEffect 钩子观察变化。像这样的东西:
useEffect(() => {
const latitude = gpsLocation?.lat;
const longtitude = gpsLocation?.lng;
const tz_name = timeZone;
console.log(latitude + " " + longtitude + tz_name);
...
}, [gpsLocation, timeZone]);