简体   繁体   中英

Cannot set object state after set attempt useState react native maps

Hi I cannot seem to set value with useState hook as you can see on pickedLocation output. When I console pickedLocation I am getting the initial values. Also my map is not showing either even with the initial values set. On IOS my message is 'No map chosen yet' as per my isFetching state and android there is a different map error Error using newLatLngBounds(...

I have tried answers here: https://stackoverflow.com/a/54069332/2277245 with useEffect and spread operator but they did not work either. Anyone help? Thanks

import React, { useState, useEffect } from "react";
import {
  Alert,
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
  Platform
} from "react-native";
import { useSelector } from "react-redux";
import MapView, { Marker } from "react-native-maps";
import Constants from "expo-constants";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import Colors from "../constants/Colors";

const MapScreen = props => {
  const availableVenues = useSelector(state => state.cafes.availableVenues);

  const [isFetching, setIsFetching] = useState(false); //spinner

  const initialValues = {
    latitude: 37.78,
    longitude: -122.43,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421
  };
  const [pickedLocation, setPickedLocation] = useState(initialValues);

  const selectItemHandler = (id, title) => {
    props.navigation.navigate("VenueDetail", {
      venueId: id,
      venueTitle: title
    });
  };

  useEffect(() => {
    if (Platform.OS === "android" && !Constants.isDevice) {
      Alert.alert(
        "Error",
        "Oops, this will not work on Sketch in an Android emulator. Try it on your device!",
        [
          {
            text: "Okay"
          }
        ]
      );
    } else {
      getLocationHandler();
    }
  }, []);

  const verifyPermissions = async () => {
    const result = await Permissions.askAsync(Permissions.LOCATION);
    if (result.status !== "granted") {
      Alert.alert(
        "Insufficient Permissions",
        "Sorry, we need location permissions to make this work!",
        [
          {
            text: "Okay"
          }
        ]
      );
      return false;
    }
    return true;
  };

  const getLocationHandler = async () => {
    const hasPermission = await verifyPermissions();
    if (!hasPermission) {
      return;
    }
    try {
      setIsFetching(true);
      const location = await Location.getCurrentPositionAsync({
        timeout: 5000
      });
      const result = {
        latitude: location.coords.latitude,
        longitude: location.coords.longitude,
        latitudeDelta: 0.1,
        longitudeDelta: 0.1
      };
      setPickedLocation({...pickedLocation,...result});
      console.log(pickedLocation); //Showing initial values
    } catch (err) {
      Alert.alert("Could Not Fetch Location", "Please Try again", [
        {
          text: "Okay"
        }
      ]);
    }
    setIsFetching(false);
  };

  return (
    <View style={styles.mapContainer}>
      {isFetching ? (
        <ActivityIndicator color={Colors.greenPrimary} size="large" />
      ) : (
        <Text>No map chosen yet!</Text>
      )}

      <MapView
        style={styles.map}
        showsUserLocation={true}
        initialRegion={pickedLocation}
        region={pickedLocation}
      >
        {availableVenues.map(marker => (
          <Marker
            key={marker.id}
            coordinate={{ latitude: marker.lat, longitude: marker.lng }}
            title={marker.title}
            description={marker.address}
            onPress={() => {
              selectItemHandler(marker.id, marker.title);
            }}
          />
        ))}
      </MapView>
    </View>
  );
};

MapScreen.navigationOptions = {
  headerTitle: "Map of Venues"
};

const styles = StyleSheet.create({
  mapContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  map: {
    justifyContent: "center",
    alignItems: "center"
  }
});

export default MapScreen;

I fixed the problem by going through the copying and adapting the example from the official expo docs https://docs.expo.io/versions/v35.0.0/sdk/location/

import React, { useState, useEffect } from "react";
import { StyleSheet, Platform } from "react-native";
import { useSelector } from "react-redux";
import MapView, { Marker } from "react-native-maps";
import Constants from "expo-constants";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";

const MapScreen = props => {
  const availableVenues = useSelector(state => state.cafes.availableVenues);

  const [isLocation, setLocation] = useState(null);

  const [mapRegion, setMapRegion] = useState({
    region: {
      latitude: -37.813629,
      longitude: 144.963058,
      latitudeDelta: 0.0922,
      longitudeDelta: 0.0421
    }
  });

  const selectItemHandler = (id, title) => {
    props.navigation.navigate("VenueDetail", {
      venueId: id,
      venueTitle: title
    });
  };

  useEffect(() => {
    if (Platform.OS === "android" && !Constants.isDevice) {
      Alert.alert(
        "Error",
        "Oops, this will not work on Sketch in an Android emulator. Try it on your device!",
        [
          {
            text: "Okay"
          }
        ]
      );
    } else {
      this._getLocationAsync();
    }
  }, []);

  _getLocationAsync = async () => {
    let { status } = await Permissions.askAsync(Permissions.LOCATION);
    if (status !== "granted") {
      Alert.alert(
        "Insufficient Permissions",
        "Sorry, we need location permissions to make this work!",
        [
          {
            text: "Okay"
          }
        ]
      );
    }
    let location = await Location.getCurrentPositionAsync({});
    setLocation({ location });
    setMapRegion({
      region: {
        latitude: location.coords.latitude,
        longitude: location.coords.longitude,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421
      }
    });
    console.log(mapRegion);
  };

  return (
    <MapView
      style={styles.map}
      showsUserLocation={true}
      initialRegion={mapRegion.region}
      region={mapRegion.region}
    >
      {availableVenues.map(marker => (
        <Marker
          key={marker.id}
          coordinate={{ latitude: marker.lat, longitude: marker.lng }}
          title={marker.title}
          description={marker.address}
          onPress={() => { //Need to change to press popup
            setTimeout(() => {
              selectItemHandler(marker.id, marker.title);
            }, 5000);
          }}
        />
      ))}
    </MapView>
  );
};

MapScreen.navigationOptions = {
  headerTitle: "Venue Map"
};

const styles = StyleSheet.create({
  map: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    paddingTop: Constants.statusBarHeight,
    backgroundColor: "#ecf0f1"
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    textAlign: "center",
    color: "black"
  }
});

export default MapScreen;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM