Adding search to Shade Map

I added search functionality to shademap.app today. The correct term is actually Geocoding, which is the process of converting search terms into latitude and longitude coordinates. Because Google is a leader in search technology, I decided to use Google Maps API for the task.

Screenshot 2021-05-05 at 13.27.36.png

I like the way the Google Maps search bar looks, so I used Developer Tools to copy the relevant markup and styles into my project as a React component. The search bar stretches from edge-to-edge on mobile devices but has a bit of margin on larger screens. I chose not to implement an auto-complete dropdown at this point because I have no revenue and the Google Autocomplete api is an extra cost. Without autocomplete, the Google Maps free-tier allows for 40,000 geocode requests per month.

Screenshot 2021-05-05 at 13.27.10.png

Some errors I encountered. The first was the result of using the wrong NPM library.

"error_message" : "API keys with referer restrictions cannot be used with this API.",

I used @googlemaps/google-maps-services-js, but the correct package was @googlemaps/js-api-loader. You also want @types/google.maps if you are coding in Typescript.

"Google Maps JavaScript API error: ApiNotActivatedMapError\nhttps://developers.google.com/maps/documentation/javascript/error-messages#api-not-activated-map-error"

Geocoding Service: This API project is not authorized to use this API.  For more information on authentication and Google Maps JavaScript API services please see: https://developers.google.com/maps/documentation/javascript/get-api-key

The above error was because I restricted my credentials to only use the Maps JavaScript API. I needed to extend the restriction to also include the Geocoding API.

Using the Google Maps Javascript API with Leaflet was very easy. Here’s the basic code:

// Initialize the Geocoder
const loader = new Loader({
    apiKey: process.env.REACT_APP_GOOGLE_MAPS_KEY as string,
});
let Geocoder: google.maps.Geocoder;

// Lookup query
const map = useMap();
Geocoder.geocode({
    address: query,
}, (results) => {
    if (results && results.length) {
        const lat = results[0].geometry.location.lat();
        const lng = results[0].geometry.location.lng();
        const ne = results[0].geometry.viewport.getNorthEast();
        const sw = results[0].geometry.viewport.getSouthWest();
        map.fitBounds([
            [ne.lat(), ne.lng()],
            [sw.lat(), sw.lng()],
        ]);
        setMarkerPosition({ lat, lng }); // state setter for map marker
    }
})
 
0
Kudos
 
0
Kudos

Now read this

Unit tests are for developers. Integration tests are for users.

I was recently tasked with teaching a fellow developer about unit testing. Tim had no testing experience prior to joining the company. Tim had learned to write Webdriver tests over the past year, but now wanted to learn about unit... Continue →