Search code examples
reactjsexpoglobal-variablesrenderlatitude-longitude

Can't find variable lat&lon, recognized everywhere except in render react


I have a working expo snack thats gets my realtime location. It also calculates the distance from a hard coded point to an array of points and gets the nearest distance to point. But when I try to replace the hard coded point with mylat&lon I get an error. Can´t find variable latitude or undefined error.

Throughout the snack I've been able to use lat/lon as {latitude}, {this.state.latitude} or as {coords.latitude}.

I also tried declaring a "const b = lat" and later const {b} = this.state and in that case I get NaN. I can´t get it to work.

export default class MyLocation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      position: 'Espere ...',
      timeInterval: null,
      latitude: null,
      longitude: null,
      speed: null,
      regionInicial: {
        latitude: -34.911203,
        longitude: -56.16737,
        latitudeDelta,
        longitudeDelta,
      },
      fill: 0,
      coordsBest: {
        latitude: null,
        longitude: null,
        speed: null,
        accuracy: null,
      },
      coords: { latitude: null, longitude: null, speed: null, accuracy: null },
Data : [{id: "1", Point: "27.1597268, 40.6646601"},
        {id: "2", Point: "11.1640393, 49.648713" },
        {id: "3", Point: "26.1539253, 42.6599287"}]
    };
  }

  idInterval = 0;

  async componentDidMount() {
  .....
    this.startTimeInterval();
  }
...
  handleCenter = () => {
    const {
      latitude,
      longitude,
      latitudeDelta,
      longitudeDelta,
    } = this.state.location;
    this.map.animateToRegion({
      latitude,
      longitude,
      latitudeDelta,
      longitudeDelta,
    });
  };

  startTimeInterval = () => {
    this.idInterval = setInterval(() => {
      this.recalcularGPS();
    }, 500);
  };

  recalcularGPS = async () => {
    clearInterval(this.idInterval);
    let location = await Location.getCurrentPositionAsync({
      enableHighAccuracy: true,
      accuracy: Location.Accuracy.higher,
      timeout: 5000,
    });
    const { latitude, longitude, speed, accuracy } = location.coords;
    const { coordsBest } = this.state;
      
        this.setState({
          latitude: latitude,
          longitude: longitude,
          speed: speed,
          error: null
        });
      (error) => this.setState({ error: error.message }),
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 0, distanceFilter: 1 }
    
    await this.setState((previousState) => ({
      position: accuracy.toFixed(2),
      fill: accuracy.toFixed(1),
      coords: location.coords,
      coordsBest:
        coordsBest.accuracy == null
          ? location.coords
          : coordsBest.accuracy > accuracy
          ? location.coords
          : coordsBest,
      regionInicial: {
        ...previousState.regionInicial,
        latitude: latitude,
        longitude: longitude,
        speed: speed,
      },
    }));
    this.startTimeInterval();

    const b = latitude
    const c = longitude
  };

  stopCalcular = async () => {
    clearInterval(this.idInterval);
  };
  componentWillUnmount() {
    clearInterval(this.idInterval);
  }

  render() {
    const { position, fill, coords, coordsBest } = this.state;
    console.log('coordsBest', coordsBest);
    console.log(coords.latitude, coordsBest.latitude);

    const { b, c } = this.state;                        //probably not OK
 
        let DistancesFromUserLocation = [];
        this.state.Data.forEach((item) => {
        DistancesFromUserLocation.push(
        getPreciseDistance(                      // This is where I get the error.    
        {latitude: {b}, longitude: {c}},         // I need to insert here my lat & long please
          item.Point
        )
      );
    });
      
    DistancesFromUserLocation = DistancesFromUserLocation.sort();
    const distances = DistancesFromUserLocation.map((distance) => (
      <Text>{distance},</Text>
    ));
    
    return (
      <View style={styles.container}>
     
         {coords && (
          <View style={{ paddingVertical: 10 }}>
            <Text>dist0: {distances[0]}</Text>    // With the hard coded coords it works 
            <Text>distances: {distances}</Text>   // With the hard coded coords it works
            <Text>Lat: {coords.latitude}</Text>   // Here they work fine
            <Text>Lon: {coords.longitude}</Text>  // Here they work fine
         </View>
        )}      
      </View>
    );
  }
}

Solution

  • It looks like the issue is being caused by the coordinate latitude and longitude being null on the initial (few?) renders.

    constructor(props) {
      super(props);
      this.state = {
        ...
        coords: {
          latitude: null,  // <-- here
          longitude: null, // <-- here
          speed: null,
          accuracy: null
        },
        ...
      };
    }
    

    You can use a null check to ensure you aren't attempting to compute a distance with undefined values.

    const { Data, coords } = this.state;
    
    const distances = Data.map(
      (item) =>
        !!(coords.longitude && coords.latitude) &&
        getPreciseDistance(coords, item.Point)
    )
      // filter falsey values
      .filter(Boolean)
      // sort distances
      .sort()
      // Wrap in <Text/> for demo
      .map((distance) => <Text>{distance},</Text>);
    

    Expo Snack