Expo-React-native-map: Find nearest restaurants from user's current-location's 5 km radius
Asked Answered
H

0

6

I am using React native maps for my app. I have restaurants data with latitude and longitude. I have setup user's current location by using expo location(Current location logic will work on real device not Simulator or expo's Snack). I sorting the restaurant locations based on latitude and longitude and display my restaurant's location by using Marker. Based on my User current location around 5 km radius I want to display nearest restaurants in the BottomSheet. When the user will Zoom out the map it will display more restaurant options and also display in the BottomSheet. I have used expo Geofence logic. But the thing I am looking I did not find anywhere in Expo documentation.

I share code in Snack. ps: this will work only ios and android not webView.

This is my map code

   import React, { ReactElement, useEffect, useRef, useState } from 'react';
import {
  Animated, Button, Dimensions, Image, PermissionsAndroid, StatusBar,
  StyleSheet, Text, TouchableOpacity, View

} from 'react-native';


import datas from './components/task.json'; 


import MapView, { Callout, Circle, Marker, PROVIDER_GOOGLE } from 'react-native-maps';
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
import { LocationGeofencingEventType } from 'expo-location';
import { FAB, Searchbar } from "react-native-paper";
import * as TaskManager from 'expo-task-manager';
import BottomSheet from "react-native-bottomsheet-reanimated";


export default function Map({ navigation }: Props): ReactElement {
    const [searchItem, setsearchItem] = useState({
    "item": ``
  });
  const [state, setstate] = useState({
    "latitude": 60.1098678,
    "longitude": 24.7385084,
    "latitudeDelta": 0.9,
    "longitudeDelta": 0.0
  });
  useEffect(() => {
     _onMapReady();
   }, []);
   const _onMapReady = async () => {
     const { status } = await Permissions.askAsync(Permissions.LOCATION);
    console.log(status);
    if (status !== `granted`) {
       console.log(`Permisson Denied`);
     }

    const location = await Location.getCurrentPositionAsync({ "accuracy": Location.Accuracy.High });
     setstate({
      ...state,
      "latitude": location.coords.latitude,
       "longitude": location.coords.longitude
     });

        Location.startGeofencingAsync(`LOCATION_GEOFENCE`, [
      {
        "identifier": `estates logs properties`,
        "latitude": state.latitude,
        "longitude": state.longitude,
        "radius": 2000,
        "notifyOnEnter": true,
        "notifyOnExit": true
      }
    ]);
   };
 const nameFilter = datas.data.filter((list) => {
    return list?.restaurant?.toLowerCase().includes(searchItem?.item?.toLowerCase());
  });
  return (
    <View style={styles.container}>
      <StatusBar hidden={true} />
      <MapView
        provider={PROVIDER_GOOGLE}
        region={state}
        showsIndoors={true}
        showsMyLocationButton={true}
        zoomControlEnabled={true}
        zoomEnabled={true}
        zoomTapEnabled={true}
        showsScale={true}
        // showsTraffic={true}
        showsBuildings={true}
        showsUserLocation={true}
        showsCompass={true}
        onMapReady={_onMapReady}
        style={styles.mapStyle} >
        {
          nameFilter?.map((i, index) => {
            return (
              <Marker
                key={index}
                coordinate={{ "latitude": i.location.lat, "longitude": i.location.lng }}
                animation={true}

              >
                <Callout
                  style={{ "width": 100, "height": 50 }}>
                  <View>
                    <Text>{i.restaurant}</Text>
                  </View>
                </Callout>
              </Marker>);
          })
        }
      </MapView>
      <Searchbar
        placeholder="Search"
        style={{
          "position": `absolute`,
          "top": 20,
          "margin": 10
        }}
          value={searchItem?.item}
        onChangeText= {(item) => setsearchItem({ ...searchItem, item })}
        icon="menu"
        onIconPress={() => {}}
      />
     <BottomSheet
        bottomSheerColor="#FFFFFF"
        initialPosition={`30%`}  // 200, 300
        snapPoints={[`30%`, `100%`]}
        isBackDropDismisByPress={true}
        isRoundBorderWithTipHeader={true}
        containerStyle={{ "backgroundColor": `#0af` }}
        header={
          <View>
            <Text style={styles.text}>Places Near you</Text>
          </View>
        }
        body={
          <View style={styles.body}>
            {datas?.data.map((i, index) => <Text key={index}>{i.restaurant}</Text>)}
          </View>
        }
      />
    </View>
  );
}

const styles = StyleSheet.create({
  "container": {
    "flex": 1,
    "backgroundColor": `#fff`,
    "alignItems": `center`,
    "justifyContent": `center`
    // position: 'absolute',
    // height: Dimensions.get("window").height,
    // width: Dimensions.get("window").width
  },
  "mapStyle": {
    // "width": 390,
    // "height": 390
    "height": Dimensions.get(`window`).height,
    "width": Dimensions.get(`window`).width
  },
  "body": {
    "justifyContent": `center`,
    "alignItems": `center`
  },
  "text": {
    "fontSize": 20,
    "fontWeight": `bold`
  }
});


TaskManager.defineTask(`LOCATION_GEOFENCE`, ({ "data": { eventType, region }, error }) => {
  console.log(`Region`, region);
  if (error) {
    // check `error.message` for more details.
    console.log(`ERROR: ` + error);
    return;
  }
  if (eventType === Location.GeofencingEventType.Enter) {
    alert(`enter in region!`);
    console.log(`You've entered region:`, region);
  } else if (eventType === Location.GeofencingEventType.Exit) {
    console.log(`You've left region:`, region);
  }
});
Hurry answered 14/11, 2020 at 7:52 Comment(4)
Basically you need to calculate the distance between user's current location and restaurants. If it's < 5km, then you need to display the restaurant. Take a look at github.com/vramosx/react-native-expo-geofence#readmeCenterboard
Thanks a lot @AnatolySukhanov. Have you tried this package? Would you please show me one example. I added my Snack in the question.Hurry
did you find the solutionRevenue
@SultanAli I changed my UI. So, I skipped that plan :). But yeah did not find the solutionHurry

© 2022 - 2024 — McMap. All rights reserved.