DEV Community

Subrat Kumar
Subrat Kumar

Posted on

How to display API data on map using React?

Introduction

Usually developers struggle with issues like how to embed maps in app, how to show data on map, etc. With this article, we will learn how to display API data on map in react application using leaflet & react-leaflet.

We will observe how based on user’s clicking anywhere on the map, coordinates (latitude and longitude) will be recorded and sent as parameters to API and then data (like nearby cities) gets fetched and displayed on the map.

Prerequisites

We need to have fair knowledge of how React works.

Why Leaflet & React-Leaflet ?

Leaflet is an open source JS library to work with interactive maps. It lets us add markers, circles, polygons, show dynamic data based on users' interactions.

React-Leaflet is a package acting as bridge between React and Leaflet. It provides useful components, hooks like MapComponent, TileLayer, Marker, useMap, useMapEvents, etc. helping users to deal with map interactivity.

Rapid API Subscription

To consume API, we have to create an account on Rapid API . Then, search for booking com:

Rapid API UI

Before using this api, we need to login/sign up and subscribe to it. Once subscribed, we will find Subscribed on the right side as shown in the above image. Finally, we are ready to consume api.

For this article, you will use Nearby Cities endpoint:

Nearby Cities endpoint

We will choose Javascript (Axios) to get the code for testing the endpoint.

Javascript code

X-RapidAPI-Key is secret key accessible for the subscribed users only. So, please don't share it with others.

Rapid API Key

Latitude, longitude and locale are mandatory parameters that needs to be passed as params while testing the api endpoint.
Enter fullscreen mode Exit fullscreen mode

Installations

Once you have the above mentioned code snippet with required parameters, move to the next step for creating React app named mapData.

With the following commands, we'll have our react app up and running at http://localhost:3000.

1. npx create-react-app mapData
2. cd mapData
3. npm start
Enter fullscreen mode Exit fullscreen mode

To embed maps in react app, you need to install following package:

npm install leaflet react-leaflet axios
Enter fullscreen mode Exit fullscreen mode

Project Structure

Once done with installations, let’s start writing code -

Project Structure will look like this:

Project Structure

Add Leaflet CSS

In index.html under public folder, write following code inside <head> tag to include Leaflet CSS file:

<link 
      rel="stylesheet" 
      href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
      integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
      crossorigin=""
    />
Enter fullscreen mode Exit fullscreen mode
  • Add following css in src/components/map/index.css which must have leaflet-container as the classname for the visibility of map:
.leaflet-container {
    width: 100vw;
    height: 100vh;
}
Enter fullscreen mode Exit fullscreen mode

Consume booking com api

Write the following code in src/api/index.js:

import axios from "axios";

export const getNearbyCities = async(coordinates) => {
    // console.log("coordinates ", coordinates)
    const {lat, lng} = coordinates;

    const options = {
        method: 'GET',
        url: 'https://booking-com.p.rapidapi.com/v1/hotels/nearby-cities',
        params: {
          latitude: lat,
          longitude: lng,
          locale: 'en-gb'
        },
        headers: {
          'X-RapidAPI-Key': 'YOUR_SECRET_API_KEY',
          'X-RapidAPI-Host': 'booking-com.p.rapidapi.com'
        }
      };

      try {
        const response = await axios.request(options);
        console.log("cities ", response.data);
        return response.data;
    } catch (error) {
          console.error(error);
      }
}
Enter fullscreen mode Exit fullscreen mode

In this code,

  • getNearbyCities accepts coordinates as parameter and coordinates value changes whenever user clicks anywhere on the map.
  • url in options uses /hotels/nearby-cities as the endpoint.
  • params contain latitude, longitude and locale
  • headers contain X-RapidAPI-Key & X-RapidAPI-Host

Displaying API Data on map

Write following code in src/components/map/index.js:

import React, { useEffect, useState } from 'react'
import { MapContainer, TileLayer, Marker, Popup, useMapEvent } from 'react-leaflet';
import './index.css'; // Very important as it loads Leaflet's CSS
import { Icon } from 'leaflet';
import { getNearbyCities } from '../../api';

// to use any marker, use following method - 
const redIcon = new Icon({
    iconUrl: require('../../img/redMarker.webp'), // path where red marker icon is located
    iconSize: [40, 40]
})

const Map = () => {
    const [marker, setMarker] = useState({lat: 51.505, lng: -0.09}) // initial coordinates of blue marker when app renders
    const [citiesLocation, setCitiesLocation] = useState([]) // it contains locations of nearby-cities 
    // fetched by api

    function SetViewOnClick() {
        const map = useMapEvent('click', (e) => {
            console.log("click event info => ", e)
            setMarker(e.latlng);  // to update the location of blue Marker
            map.setView(e.latlng, map.getZoom())
        })
        return null;
    }

    useEffect(() => {
        console.log("e.latlng ",marker)
        getNearbyCities(marker) // passing marker as coordinates to fetch nearby-cities' locations
        .then(data => setCitiesLocation(data))
        .catch(err => console.log(err));
    },[marker])

    return (
        <MapContainer
            center={marker}
            zoom={12}
            scrollWheelZoom={true} 
        >
            <TileLayer
                attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            <Marker position={marker}>
                <Popup>
                    See this
                </Popup>
            </Marker>
            {
                citiesLocation?.map((item, index) => (  // at each city location, redIconed marker will be visible
                    <Marker key={index} icon={redIcon} position={[item.latitude, item.longitude]}>
                        <Popup>
                            {item.name}, {item.country}
                        </Popup>
                    </Marker>
                ))
            }
            <SetViewOnClick />
        </MapContainer>
    )
}

export default Map;
Enter fullscreen mode Exit fullscreen mode

In the above code,

  • const [marker, setMarker] = useState({lat: 51.505, lng: -0.09}) indicates initial coordinates of blue marker (check in Output section) when app renders
  • const [citiesLocation, setCitiesLocation] = useState([]) will contain locations of nearby-cities fetched by api
  • function SetViewOnClick() updates the location of blue marker based on user's click as well as view just by clicking on the map.
  • map.setView(e.latlng, map.getZoom()) sets the view of the map to the location where clicked and zooms
  • useEffect(() => { ... },[marker]) have dependency array containing marker, It means on changing marker's value, useEffect will trigger, getNearbyCities executes and populates citiesLocation
  • <MapContainer center={marker} zoom={12} scrollWheelZoom={true}>...</MapContainer> has center showing the center of the map, zoom showing zoom level and scrollWheelZoom to decide whether map can be zoomed using mouse scroll wheel.
  • <TileLayer attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> We need to add Tile layer to our map, in our case it's OpenStreetMap tile layer and it requires an attribution. Thereafter, map loads.
  • <Marker position={marker}> <Popup> See this </Popup> </Marker> shows the marker with the popup (when clicked)

Rendering of Map inside src/App.js

import React from 'react';
import './App.css';
import Map from './components/map';

function App() {
  return (
    <div className="App">
      <Map/> {/** Map component will contain the map shown in our React app */}
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

And, then <App/> inside src/index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <div>
    <App />
  </div>
);
Enter fullscreen mode Exit fullscreen mode

Output

Final output -

On rendering, map shows following data:

  1. Blue marker shows coordinates(lat: 51.505, lng: -0.09) of Southwark London England United Kingdom.
  2. Red markers show cities' locations nearby London, UK.

Locations nearby London, UK

Check the console tab in developer console after rendering:

dev console after rendering

After clicking anywhere on the map, blue marker's position gets updated and accordingly, cities' locations update.

Check out following image:

cities locations

Check the console tab in developer console after clicking:

dev console after clicking

Popups with location names

location names

location name

Conclusion

With this article, now you would be able to embed maps in react app and play around with it as per your requirements.

References

https://leafletjs.com/examples/quick-start/
https://react-leaflet.js.org/docs/start-setup/

Top comments (0)