React Native 自定义钩子返回未定义的状态

问题描述 投票:0回答:1

我当前遇到一个问题,即挂钩返回的值意外未定义,而不是预期值。虽然 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 值给了我未定义的值。

有人知道修复方法吗?

javascript reactjs react-native react-hooks hook
1个回答
0
投票

状态正在异步改变。使用 useEffect 钩子观察变化。像这样的东西:

useEffect(() => {
  const latitude = gpsLocation?.lat;
  const longtitude = gpsLocation?.lng;
  const tz_name = timeZone;

  console.log(latitude + " " + longtitude + tz_name);
...
}, [gpsLocation, timeZone]);
© www.soinside.com 2019 - 2024. All rights reserved.