Yelp Fusion API and Geolocation API with React Native

Valerie Rojdestvenskaia
7 min readSep 30, 2018

--

Yesterday I completed my presentation for my app Chill Traveler at Fullstack Academy. During “senior phase” all the students work on individual projects and are inspired to shoot as high as they can with their ideas, we are given a few days to complete it. I was really interested in creating a mobile app that uses geolocation with the theme of travel. I realized while working on it though that there wasn't much documentation for what I was trying to do and I felt that a better guide could have helped me progress further in the implementation of my app. If you find the below guide helpful, leave a clap!

Geolocation API

The geolocation api is available using navigator.geolocation and you don’t need to import it. Make sure though that you get a google api key and input that into your project. Regarding permissions, for IOS you do not necessarily need to include a permission request, whereas on Android you do and you can use something per the below snippet:

import { PermissionsAndroid } from 'react-native';async requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Access Permission',
'message': 'This App needs access to your location ' + 'so you can use it.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location")
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
}

For testing my app I used expo which can be run on your phone as well as on your computer, definitely take a look at it as the setup is pretty quick and its a really great option. I have an iPhone and a Mac and have not had any problems. Though it does take getting used to using the “shake gesture” to restart your app if you made changes to your code.

Now to get the current user location, we can use getCurrentPosition() method, which is all I needed for a simple app but there is also watchPosition and clearWatch methods that you can utilize. There is more information on these in the official react native docs. Geolocation is based on a users latitude and longitude, so we store these in state and in the code below I have a default location plugged in. You can also play the lat/long deltas, I have edited them to zoom into the users location.

import React from 'react';
import { MapView } from 'expo';
export default class Map extends React.Component {
constructor() {
super();
this.state = {
origin: { latitude: 40.7050758, longitude: -74.0091604 },
};
getLocation = () => {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
position => {
let newOrigin = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
};
this.setState({
origin: newOrigin,
});
resolve(true);
},
err => {
console.log(err);
reject(reject);
},
{ enableHighAccuracy: true, timeout: 2000, maximumAge: 1000 }
);
});
};
async componentDidMount() {
await this.getLocation();
}
render() {
return (
<MapView
style={{ flex: 1 }}
provider="google"
region={{
latitude: this.state.origin.latitude,
longitude: this.state.origin.longitude,
latitudeDelta: 0.0100,
longitudeDelta: 0.0100,
}}
>
<MapView.Marker coordinate={this.state.origin}/>
</MapView>
);
}
}

Volia! your app should now be rendering a map view with your location(if you are using expo on the computer it may show you San Francisco default location but your location would show on your phone with the expo app). If you are having any trouble I would suggest trying to run a simple message like “Hello World” to show up on your app just to be sure there are no issues with your initial setup. Below in the extras section i’ll show how my expo is set up and how I styled the app.

Yelp API

The theme of my app was travel so I was searching for an API that can render “tourist attractions”. Yelp API Fusion was a really great choice, below are many different ways you can use the api:

  • Search: Find businesses by keyword, location, category, open now and price level
  • Phone Search: search for businesses using a phone number
  • Transaction Search: Search for businesses which support food delivery transactions
  • Business Details: find rich business data, such as photos, Yelp rating, price levels and hours of operation
  • Reviews: find up to 3 review excerpts for a business
  • Autocomplete: provides autocomplete suggestions for businesses, search keywords, and categories

I used “search” to find the locations I needed by keyword, Yelp’s documentation is actually very helpful for example if you navigate to their search docs, you will see the response body section which will show you how to access different types of data you may need.

To use the API you should first get your API key and then store it in an environment variable in your project(to keep it secret).

Next I used axios to fetch the marker data, you will need to import axios. Also I left some comments in the code snippet below for “config” where you will want to edit at least the limit, sort_by, term and don’t forget to input your yelp api key. The code below is together already with geolocation. The MapView.Marker is how your markers will show up on the map, in the code there is a title and description within the marker that will show up as a callout on each marker but you can also create a custom callout or just edit the details being rendered in the title and description(currently in the code, it’s showing the marker name, rating and address).

import React from 'react';
import { MapView } from 'expo';
import { Linking, Alert } from 'react-native';
import axios from 'axios';
export default class Map extends React.Component {
constructor() {
super();
this.state = {
isLoading: true,
markers: [],
origin: { latitude: 40.7050758, longitude: -74.0091604 },
};
config = {
headers: {
Authorization: 'Bearer <"YOUR YELP API KEY">',
},
params: {
term: 'Tourists Must See List',
//term to search locations by
raduis: 0.5,
latitude: this.state.origin.latitude,
longitude: this.state.origin.longitude,
// for lat/long we are searching locations by proximity of users location which is the location from geolocation api
sort_by: 'distance',
//can sort by best_match, rating, review_count or distance

limit: 5,
//the amount of location markers you want to show
},
};
}
getLocation = () => {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
position => {
let newOrigin = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
};
config.params.latitude = newOrigin.latitude;
config.params.longitude = newOrigin.longitude;
this.setState({
origin: newOrigin,
});
resolve(true);
},
err => {
console.log('error');
console.log(err);
reject(reject);
},
{ enableHighAccuracy: true, timeout: 2000, maximumAge: 1000 }
);
});
};
async componentDidMount() {
await this.getLocation();
await this.fetchMarkerData();
}
fetchMarkerData() {
return axios
.get('https://api.yelp.com/v3/businesses/search', config)
.then(responseJson => {
this.setState({
isLoading: false,
markers: responseJson.data.businesses.map(x => x),
});
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<MapView
style={{ flex: 1 }}
provider="google"
region={{
latitude: this.state.origin.latitude,
longitude: this.state.origin.longitude,
latitudeDelta: 0.0100,
longitudeDelta: 0.0100,
}}
>
{this.state.isLoading
? null
: this.state.markers.map(marker => {
const coords = {
latitude: marker.coordinates.latitude,
longitude: marker.coordinates.longitude,
};
const nameOfMarker = `${marker.name}(${marker.rating} rating)`;
const addressOfMarker = `${marker.location.address1}, ${marker.location.city}`;
return (
<MapView.Marker
key={marker.id}
coordinate={coords}
title={nameOfMarker}
description={addressOfMarker}
>
</MapView.Marker>
);
})}
<MapView.Marker coordinate={this.state.origin}>
</MapView.Marker>
</MapView>
);
}
}

Extra Information

Custom markers

Using “react-native-vector-icons” you can add custom markers and colors. For example for the user location you can have a human looking marker and maybe a coffee looking marker for coffee locations. There are alot of icons to choose from, i used FontAwesome. Make sure to npm install it and import it.

import Icon from 'react-native-vector-icons/FontAwesome';

Then just add Icon in between the marker tags, you can edit the size, color and the name of the icon to use. Yes, its that simple!

<MapView.Marker>
<Icon name="street-view" size={40} color={'#76BBB7'} />
</MapView.Marker>

Expo Settings

I used IOS only for my app and the below was my configuration for using expo(put this under a seperate ‘app.json’ file)

"expo": {
"name": "Name of your app",
"icon": "",
"version": "1.0.0",
"platforms": ["ios"],
"orientation": "portrait",
"slug": "name",
"sdkVersion": "27.0.0",
"ios": {
"config": {
"googleMapsApiKey": "insert your google api key here"
}
}
}
}

App Header

In a separate component you can create a header, the below example snippet is a basic header with one color fill and a title but you can change it up and add Icons in your header, similar to the above. Play with the colors, positioning, etc. You will need to tie the Map component together with the Map component you created, one way to do it is to import it into the header component and input the tag per the below example.

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Name of App</Text>
</View>
//<Map/> - can add your Map component in here to tie the two components together.
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
alignItems: 'center',
justifyContent: 'center',
flex: 0.2,
backgroundColor: '#76BBB7',
},
title: {
fontFamily: 'Marker Felt',
fontSize: 30,
color: '#E7E7E6',
},
});

I hope this guide glued together some pieces. I used “create-react-native-app” to start my project. This is what the end result looks like on ios:

--

--