React Native Restaurant Review App – Part 1

Today we are starting a new series tutorial of “Building a Restaurant Review App” using React Native. Using this app, users will be able to check list of restaurants near by and then ( after using the restaurant service,) they will be able to leave rating and review for the restaurant in an interactive way.

Download Demo App

So, in this part of tutorial, we will be coding how to list restaurant near by. For this we will be using Google Places Api. To use Google Places Api first we need to create API key by going to Google Developer Console.

Below is the code to find and List near by restaurants :

import React, { Component } from 'react';
import {
  Text,
  View,
  FlatList,
  ActivityIndicator,
  AppRegistry
} from 'react-native';

import { List, ListItem } from "react-native-elements";
var _ = require('lodash');

export default class ResturnatList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      loading: false,
      data: [],
      pageToken: '',
      refreshing: false,
      siteTitle: ''
    };
  }

  componentDidMount() {

    this.fetchData();
  }

  fetchData = () => {

    navigator.geolocation.getCurrentPosition(
            (position) => {
    const latitude = Number(position.coords.latitude.toFixed(6));
    const longitude = Number(position.coords.longitude.toFixed(6));
    const { pageToken } = this.state;
    const urlFirst = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude},${longitude}&radius=500&type=restaurant&key=Your_Api_Key
    `
    const urlNext = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude},${longitude}&radius=500&type=restaurant&key=Your_Api_Key&pagetoken=${pageToken}`;

    let url = pageToken === '' ? urlFirst : urlNext
    console.log(url);
    console.log("url");
    this.setState({ loading: true });
    fetch(url)
      .then(res => {
        return res.json()
      })
      .then(res => {

        const arrayData = _.uniqBy( [...this.state.data, ...res.results] , 'id' )

        this.setState({
          siteTitle: "Resturants Near By",
          data: pageToken === '' ? res.results : arrayData,
          loading: false,
          refreshing: false,
          pageToken: res.next_page_token
        });

      })
      .catch(error => {
        console.log(error);
        this.setState({ loading: false });
      });
    })
  };
  renderSeparator = () => {
   return (
     <View
       style={{
         height: 1,
         width: "86%",
         backgroundColor: "#CED0CE",
         marginLeft: "14%"
       }}
     />
   );
  };
  renderHeader = () => {
    return (<Text style={{ alignSelf: "center", fontWeight: "bold", fontSize: 20, marginBottom: 10}}>{this.state.siteTitle}</Text>)
  };
  renderFooter = () => {

    if (this.state.pageToken === undefined) return null;

    return (
      <View
        style={{
          paddingVertical: 20,
          borderTopWidth: 1,
          borderColor: "#CED0CE"
        }}
      >
        <ActivityIndicator animating size="large" />
      </View>
    );
  };

  handleRefresh = () => {
    this.setState(
      {
        pageToken: '',
        refreshing: true
      },
      () => {
        this.fetchData();
      }
    );
  };

  handleLoadMore = () => {
    this.fetchData();
  };
  render() {
  
    return (
      <View>    
      <List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }} >
      <FlatList
        data={this.state.data}
        keyExtractor={item => item.id}
        ListHeaderComponent={this.renderHeader}
        ListFooterComponent={this.renderFooter}
        renderItem={({ item }) =>{
   
          const rating = item.rating ? item.rating : 'na'

          return (<View><ListItem
              roundAvatar
              title={`${item.name}`+" ("+`${rating}`+")"}
              subtitle={`${item.vicinity}` }
              avatar={{ uri: item.icon }}
              containerStyle={{ borderBottomWidth: 0 }}
            />
            <View
              style={{
                height: 1,
                width: "86%",
                backgroundColor: "#CED0CE",
                marginLeft: "14%"
              }}
            /></View>
          )
        }}
        onRefresh={this.handleRefresh}
        refreshing={this.state.refreshing}
        onEndReached={this.handleLoadMore}
        onEndReachedThreshold={50}
      />
      </List>
      </View>
    );
  }
}

In the above code, we are first retrieving latitude and longitude of current location using navigator.geolocation api. Next we are creating Google Places Api endpoint. In the endpoint we are using following parameters :

  1. Latitude and longitude – of place we want to search restaurant
  2. Radius –  to specify the distance till where we want to search restaurant
  3. Type – to specify that we want to search places of type restaurant

First time we make a request we get 20 array objects in response and a next page token. Using the token we can fetch another 20 array of objects and in this way we can keep fetching and implement the pagination feature.

Sometimes Google Places API return duplicate results, so, we have used lodash _.uniqBy function to make sure that we only get unique results.

To List places we are using FlatList component in very similar way like we used it in our previous two tutorials. So using FlatList we are rendering restaurant name, restaurant icon, restaurant rating and restaurant address. We are using Place ID as key for the FlatList.

So, in this part of tutorial we learned how we can fetch nearby restaurants using Google Places Api.  In next part we will use the Resturant List to collect rating and Reviews in an interactive way.

If you like this tutorial then make sure you subscribe to our news letter for more such informative and useful stuffs.

Download Demo App