Adding Advanced TomTom API Features to a Modern React App
David Atanda·Aug 25, 2021

Adding Advanced TomTom API Features to a Modern React App

David Atanda
Aug 25, 2021 · 10 min read

These days, digital maps are critical for navigating cities and continents. Digital maps provide access to directions in real-time to guide travelers. This article shows you how to create a digital map by integrating the advanced mapping features of TomTom’s Search API and Routing API into a modern React web app.

Digital maps like TomTom’s have become critical for navigation around cities and across continents. We now have access to real-time directions to guide us when moving from one location to other.

Plus, we can even get information about a place to enhance our user experience. For instance, we can search for a restaurant and get the address, website, and sometimes even pictures to better understand its atmosphere.

In a previous article, we explored how to add a TomTom map to a modern React app. In this article, we’ll discuss how to use two other TomTom APIs in a React app: the Search API and Routing API. We’ll build a component in React enabling users to search for a location and get a list of responses fulfilling the request.


Then, we’ll build another component to find the distance between two locations using their unique latitude and longitude. The response will contain information like the distance between them and the time to complete the journey.

You should be familiar with React and JavaScript to follow along. You can also find a demo on CodeSandbox. Adding TomTom maps to a React app is painless. Let’s get started.


Setting Up Our Tools

Installing Node.js

To create a React app, we first need to ensure we have Node.js installed on our computer. If you haven’t built a React app before, you can check to see if you have Node.js installed by typing the following into your terminal:

1node -v

If you don't have it, go to the Node.js website to download the latest version.

Creating a React App

Once that’s complete, we can get started with our React app by running this command:

1npx create-react-app tomtom-maps                                            

Then, we navigate into our project folder on the terminal:

1cd tomtom-maps
Installing React-Toastify

Let’s also install react-toastify to show errors:

1npm i react-toastify
Installing TomTom’s Tools

To use TomTom’s searching and routing services, we first need to install the TomTom Maps SDK. We use this command to install the library:

1npm i @tomtom-international/web-sdk-services

Then we also install TomTom’s Maps SDK to view the map on the Document Object Model (DOM):

1npm i @tomtom-international/web-sdk-maps

To use these services in your app, you first need to register as a TomTom developer. It’s free to sign up. Once you’re signed up, you can enjoy thousands of transactions daily — even for commercial applications. If your app’s popularity skyrockets later, you can always pay as you grow.

You’ll get an API Key with your account. Take note of the API key, because we’ll come back to it shortly.

Using the TomTom Search API

By default, TomTom’s Search API performs a fuzzy search when we make a query. If our queries contain the name of a specific place, like schools, hospitals, or restaurants, for example, it treats them as Points of Interest (POI).

The fuzzy search typically takes the query and returns all related results. These results enable us to locate addresses and POIs that partially match a specific query text.

To create our search component, we’ll use function components with React Hooks.

First, we import the library tt (see below). Also, we import useState to help us control our state within the component:

1import tt from "@tomtom-international/web-sdk-services";
2import { useState } from "react";

Then, we use useState to initialize our <input/> string’s state. It also handles the result object we get back after sending the query.

1  const [name, setName] = useState("");
2  const [result, setResult] = useState({});

Within our functional component, we next create a function to handle the search logic. We pass the argument name into fuzzySearch, where it acts as our query. We also use the API key as an input here. Then, we assign res.results from our query to our result state using setResult.

1  const fuzzySearch = (name) => {
3      .fuzzySearch({
4        key: "<Your API Key>",
5        query: name
6      })
7      .go()
8      .then((res) => {
9        console.log(res);
10        const amendRes = res.results;
11        console.log(amendRes)
12        setResult(amendRes)
13        console.log(result)
14      })
15      .catch((err) => {
16        console.log(err);
17      });
18  };

Next, we loop through the results and list them. Then, write a new function and use a ternary operator to check when the result object populates. When it’s populated, we loop through it using map(). If it’s empty, it displays No location.

1const resultList = (result.length > 0) ?
2 => (
3    <div className="col-xs-12 col-md-4 col" key={}>
4      <div className="box">
5        <ResultBox result={resultItem} />
6      </div>
7    </div>
8  )): <h2>No locations</h2>

Our <ResultBox/> component looks like this:

1import React from 'react'
2const ResultBox = ({result}) => (
3  <div className="result">
4    <div className="result-name">Location Address: {result.address.freeformAddress}</div>
5    <div className="result-name">Location state: {result.address.localName}</div>
6    <div className="result-name">Location country: {}</div>
7    <div className="result-type">City: {result.address.municipalitySubdivision}</div>
8    {result.poi ?
9      <div className="result-name">Location name: {}</div>
10        :
11      <h4>Location has no specific name</h4>
12    }
13  </div>
15export default ResultBox

Here we have the data that we'll display to the user. We also write another ternary operator to check if the result contains a POI object. If it does, it shows If not, it displays “Location has no specific name.”

Additional information is available inside the result object that we can use if needed.

Displaying Our Component

Now that we’ve set up the Search API, we display our component. To do that, we return this:

1<div className="App">
2      <input
3        className="input"
4        type="text"
5        placeholder="Search Location"
6        value={name}
7        onChange={(e) => {
8          setName(;
9        }}
10        onKeyPress={(e) => {
11          if (e.key === "Enter") {
12            fuzzySearch(name);
13          }
14        }}
15        required
16      />
17      {resultList}
18    </div>

Anything we add, our input tag syncs with name using setName(). When we press the Enter key after typing, it triggers the fuzzySearch function and passes name as an argument. The {resultList} function also displays in the component.

Here’s the full component code block:

1import "../styles.css";
2import tt from "@tomtom-international/web-sdk-services";
3import { useState } from "react";
4import ResultBox from "./resultBox";
6export default function FuzzySearch() {
7  const [name, setName] = useState("");
8  const [result, setResult] = useState({});
10  const fuzzySearch = (name) => {
12      .fuzzySearch({
13        key: "<Your API Key>",
14        query: name
15      })
16      .go()
17      .then((res) => {
18        console.log(res);
19        const amendRes = res.results;
20        console.log(amendRes)
21        setResult(amendRes)
22        console.log(result)
23      })
24      .catch((err) => {
25        console.log(err);
26      });
27  };
29  const resultList = (result.length > 0) ?
30 => (
31    <div className="col-xs-12 col-md-4 col" key={}>
32      <div className="box">
33        <ResultBox result={resultItem} />
34      </div>
35    </div>
36  )): <h2>No locations</h2>
38  return (
39    <div className="App">
40      <input
41        className="input"
42        type="text"
43        placeholder="Search Location"
44        value={name}
45        onChange={(e) => {
46          setName(;
47        }}
48        onKeyPress={(e) => {
49          if (e.key === "Enter") {
50            fuzzySearch(name);
51          }
52        }}
53        required
54      />
55      {resultList}
56    </div>
57  );

Using the TomTom Routing API

We next include TomTom’s Routing API. Similar to the Search API section, we import tomtom and useState. However, we also import react-toastify just in case we need to display an error.

1import tt from "@tomtom-international/web-sdk-services";
2import * as ttmaps from "@tomtom-international/web-sdk-maps"
3import { useState, useRef, useEffect } from "react";
4import { ToastContainer, toast } from "react-toastify";
5import "react-toastify/dist/ReactToastify.css";

We also use useState to hold our component’s state, which includes:

  • Start location’s latitude

  • Start location’s longitude

  • Destination’s latitude

  • Destination’s longitude

Plus, we use useRef to add the map to the DOM:

1const [startLatitude, setStartLatitude] = useState("");
2const [startLongitude, setStartLongitude] = useState("");
3const [destinationLatitude, setDestinationLatitude] = useState("");
4const [destinationLongitude, setDestinationLongitude] = useState("");
5const [result, setResult] = useState({});
6const mapElement = useRef();
7const [map, setMap] = useState({});
8const [longitude, setLongitude] = useState(-121.91599);
9const [latitude, setLatitude] = useState(37.36765);

After the component loads, we automatically add the map to the DOM with useEffect. We add it to the mapElement ref, and the map centers with the latitude and longitude we have declared.

1useEffect(() => {
2    let map ={
3      key: "74x6pNZKyjeAejlBl8V1O6BQLWKaALJC",
4      container: mapElement.current,
5      stylesVisibility: {
6        trafficIncidents: true,
7        trafficFlow: true
8      },
9      center: [longitude, latitude],
10      zoom: 14
11    });
12    setMap(map);
13  }, [])

Next, we write our calculateRoute function that holds the logic behind calculating the route between two different locations. The function uses our API key and the start location’s and destination’s latitude and longitude in the format below. We use template literals to represent everything in a string.

We then store the response inside the result state using setResult and automatically center the map on the startLatitude and startLongitude.

1const calculateRoute = () => {
3      .calculateRoute({
4        key: "<Your API Key>",
5        locations: `${startLatitude},${startLongitude}:${destinationLatitude},${destinationLongitude}`
6      })
7      .go()
8      .then(function (routeData) {
9        map.setCenter([parseFloat(startLatitude), parseFloat(startLongitude)]);
10        console.log(routeData.toGeoJson());
11        const data = routeData.toGeoJson();
12        setResult(data);
13      })
14      .catch((err) => {
15        console.log(err);
16        notify();
17      });
18  };

Then, resultList checks whether the result populates. If it’s populated, we can calculate and display the distance and time. If not, the app displays Add location to get route details instead. If there’s an error, it triggers notify.

1const resultList = result.features ? (
2    <div className="col-xs-12 col-md-4 col" key={}>
3      <div className="box">
4        <div className="result">
5          <h4>
6            Distance in KM : {result.features[0].properties.summary.lengthInMeters / 1000}
7          </h4>
8          <h4>
9            Time Estimate for Journey is
10            {` ${result.features[0].properties.summary.travelTimeInSeconds / 60} minutes`}
11          </h4>
12        </div>
13      </div>
14    </div>
15  ) : (
16    <h4>Add location to get route details</h4>
17  );
18  const notify = () => toast("Locations cannot be mapped. Check and map again");

Eventually, our user’s display includes the four input elements for the latitude and longitude pair, the button that triggers the calculateRoute, and the {resultList} to display the result. We add <ToastContainer /> so the notification toaster can pop up when needed.

1<div className="App">
2      <ToastContainer />
3      <div>
4        <h3>Start Location</h3>
5        <input
6          className="input"
7          type="text"
8          placeholder="Latitude"
9          value={startLatitude}
10          onChange={(e) => {
11            setStartLatitude(;
12          }}
13          required
14        />
15        <input
16          className="input"
17          type="text"
18          placeholder="Longitude"
19          value={startLongitude}
20          onChange={(e) => {
21            setStartLongitude(;
22          }}
23          required
24        />
25        <h3>Destination</h3>
26        <input
27          className="input"
28          type="text"
29          placeholder="Latitude"
30          value={destinationLatitude}
31          onChange={(e) => {
32            setDestinationLatitude(;
33          }}
34          required
35        />
36        <input
37          className="input"
38          type="text"
39          placeholder="Longitude"
40          value={destinationLongitude}
41          onChange={(e) => {
42            setDestinationLongitude(;
43          }}
44          required
45        />
46      </div>
47      <button
48        onClick={(e) => {
49          calculateRoute();
50        }}
51      >
52        Calculate routeData
53      </button>
54      {resultList}
55      <div className="map" ref={mapElement}></div>
56    </div>

Finally, we go into App.js and use react-router-dom to handle navigation inside this project. We import all the components and use the router library to create routes.

1import "./styles.css";
2import FuzzySearch from "./components/FuzzySearch";
3import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
4import CalculateRoute from "./components/CalculateRoute"
5export default function App() {
6  return (
7    <Router>
8      <h3><Link to="/">Search Location/Address</Link></h3>
9      <h3><Link to="/calculate">Calculate Route Distance</Link></h3>
10    <Switch>
11      <Route path='/' exact component={FuzzySearch} />
12      <Route path='/calculate' component={CalculateRoute} />
13    </Switch>
14  </Router>
15  );

We now have a simple mapping app for a user to search for a location. The app displays related results, including Points of Interest. Our other app component calculates a route between the user’s start location and destination, helping them get to where they need to go.

Next Steps

We have explored how to use TomTom’s Search API to find addresses and locations. We also covered using the Route API to calculate road distance and travel time. Plus, we integrated it all into a React application.

You can further challenge yourself to explore TomTom maps in your React app by connecting the two components we’ve built. Search for locations, select two separate places (each location Search API returns has a latitude and longitude), and find the distance between them directly within the app.

Now that you see how easy it is to place interactive TomTom maps within your React app and some of the features that will enhance your users’ experience, you can add maps to your next great app for free. Sign up to learn more and start using TomTom Maps!

Get the developer newsletter.
No marketing fuff. Tech content only.

* Required field. By submitting your contact details to TomTom, you agree that we can contact you about marketing offers, newsletters, or to invite you to webinars and events. We could further personalize the content that you receive via cookies. You can unsubscribe at any time by the link included in our emails. Review our privacy policy.