Get API Credentials
We now have our user's location to find our restaurants stored safely within our components state! But before we can make our API call to the Google Places API to receive our list of restaurants, we need to get an API key from Google. Go ahead and open a web browser and navigate to the Google developer console and log in with your Google account. From here you are going to click the drop-down which says "select a project" and then click on a "new project". From here you can name the project. We are also going to leave the organization section blank for now.
After your project is created, you are then going to go to the library tab and search for the Google Places API within the marketplace. Once found go ahead and add the library to your account.
After the Google places API is added to your Google developer account, find and click on the tab that says credentials from the home page. Once in the credentials tab, you are going to press the plus button with the text "Create Credentials" next to it and then select the "API key" option. Under the API keys section, there should be a new key labeled API key 1.
Underneath the "key" column is going to be the API key we are going to use in our project.
Creating Our Fetch URL
Now that we have the necessary credentials in order to access the Google Places API, we are going to make a fetch call in order to search for nearby restaurants when our "Search Restaurants" touchable opacity is clicked.
The first thing we are going to do is create our handleRestaurantSearch method. Within our App class above our render function, go ahead and add the lines
handleRestaurantSearch = () => {
}
Now within our new method, we are going to add the building blocks of our URL string to make the API call. The first part of which begins with the base URL. Let us create a constant variable within our method named URL and set it equal to "https://maps.googleapis.com/maps/api/place/nearbysearch/json?". The variable should look like this:
const url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?'
After this, we need to add the user's location to the string which we have stored within our app's state.
We are going to create a constant variable named location and set it equal to our latitude and longitude like so.
const location = `location=${this.state.latitude},${this.state.longitude}`;
After that, we need to specify the radius of our search in meters, the type of search we are doing, and our API key. To do this we can create another three variables.
const radius = '&radius=2000';
const type = '&keyword=restaurant';
const key = '&key=<ENTER YOUR API KEY HERE>';
At the very end, we can add all our string variables together to create our final string which will be passed as our API call.
const restaurantSearchUrl = url + location + radius + type + key;
In the end, your handleRestaurantSearch method should look like so.
handleRestaurantSearch = () => {
const location = `location=${this.state.latitude},${this.state.longitude}`;
const radius = '&radius=2000';
const type = '&keyword=restaurant';
const key = '&key=<YOUR API KEY>';
const restaurantSearchUrl = url + location + radius + type + key;
}
Fetching our Data
Now that our string is built, we can make a fetch for our data. Below our new variables, we create a fetch request using the JavaScript fetch() function, and within the parameters, enter our restaurantSearchUrl.
fetch(restaurantSearchUrl)
Since fetch is a promise, we are going to use a .then right below our fetch request to handle when the promise is resolved and parse the JSON we were sent from Google.
.then(response => response.json())
After that promise is resolved, we are going to change the restaurantList key within our state to match whatever we were sent back by this fetch request.
.then(result => this.setState({restaurantList: result}))
Our handleRestaurantSearch method should now look something like this.
handleRestaurantSearch = () => {
const url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?'
const location = `location=${this.state.latitude},${this.state.longitude}`;
const radius = '&radius=2000';
const type = '&keyword=restaurant';
const key = '&key=<YOUR API KEY>';
const restaurantSearchUrl = url + location + radius + type + key;
fetch(restaurantSearchUrl)
.then(response => response.json())
.then(result => this.setState({restaurantList: result}))
}
Now in order to call our handleRestaurantSearch method, we need to create an event listener within our TouchableOpacity. within our <TouchableOpacity>
tag we are going to add the following lines to create an onPress event listener.
<TouchableOpacity onPress={() => this.handleRestaurantSearch()}>
We are also going to add a console.log() to our render function to test to see whether our restaurant list is showing up within our state. To do this we can add console.log(this.state.restaurantList); right below our render method but above the return statement.
Now from our physical device or emulator, we can press "Search Restaurants" and within our terminal, we should see a long list of JSON describing 20 nearby restaurants.
Displaying Our List of Restaurants
Now that we have our list of restaurants ready to go we can now list them within our FlatList. Within our FlatList tag we are going to set a few attributes.
The first attribute we are going to set is the data attributes. We are going to assign this to our restaurantList's results we have contained within our state.
<FlatList
data={this.state.restaurantList.results}
>
We are going to then create a keyExtractor to make sure each item on the list has a unique identifier. We are going to set each item's key to its place_id.
<FlatList
data={this.state.restaurantList.results}
keyExtractor={(item) => item.place_id}
>
The last thing we need to do before our FlatList is complete is to add the renderItem attribute. Here we can call what kind of tags our list is going to use. For this example, we are just going to use a text tag that will display a nearby restaurant's name. I'm also going to add the tiniest bit of styling to our list to make it more visible once finished. To do this add the following attributes after the keyExtractor.
<FlatList
data={this.state.restaurantList.results}
keyExtractor={(item) => item.place_id}
renderItem={({item}) => (
<Text>{item.name}</Text>
)}
style={{backgroundColor: 'grey', width: '80%', margin: 60, padding: 5}}
/>
After this, we should be finished with our list meaning that when you click on the "Search Restaruants" TouchableOpacity within your phone or emulator, we should see a list of restaurants that looks like so.
In the end. Our entire App.js file should look like so.
import React from 'react'
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, FlatList, TouchableOpacity } from 'react-native';
import * as Permissions from 'expo-permissions';
import * as Location from 'expo-location';
export default class App extends React.Component {
state = {
hasLocationPermission: false,
latitude: 0,
longitude: 0,
restaurantList: []
}
componentDidMount() {
this.getLocationAsync();
}
async getLocationAsync () {
const { status } = await Permissions.askAsync(
Permissions.LOCATION
);
if (status === 'granted') {
let location = await Location.getCurrentPositionAsync({});
this.setState({
hasLocationPermissions: true,
latitude: location.coords.latitude,
longitude: location.coords.longitude,
});
} else {
alert('Location permission not granted');
}
};
styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
handleRestaurantSearch = () => {
console.log("here")
const url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?'
const location = `location=${this.state.latitude},${this.state.longitude}`;
const radius = '&radius=2000';
const type = '&keyword=restaurant';
const key = '&key=AIzaSyCTG8tfRBCabaCP-enskC2akmNVBvaOAAs';
const restaurantSearchUrl = url + location + radius + type + key;
fetch(restaurantSearchUrl)
.then(response => response.json())
.then(result => this.setState({restaurantList: result}))
.catch( e => console.log(e))
}
render() {
console.log(this.state.restaurantList.results)
return (
<View style={this.styles.container}>
<FlatList
data={this.state.restaurantList.results}
keyExtractor={(item) => item.place_id}
renderItem={({item}) => (
<Text>{item.name}</Text>
)}
style={{backgroundColor: 'grey', width: '80%', margin: 60, padding: 5}}
/>
<TouchableOpacity onPress={() => this.handleRestaurantSearch()}>
<Text style={{backgroundColor: 'grey', color: 'white', padding: 20, marginBottom: 50}}>Search Restaurants</Text>
</TouchableOpacity>
<StatusBar style="auto" />
</View>
);
}
}
And that is how to create a nearby restaurant finder within React-Native! Note that tons of information such as the restaurant's address, rating, and photos are also given with our API call which we can also use within our list. If you wanted to do a keyword search to find a specific restaurant instead of just a list of nearby restaurants you can use the Google Places API text search instead.
Top comments (0)