Integrating ReactJS, Mapbox, and Mapbox Directions

Tyler Eaden
Level Up Coding
Published in
7 min readMay 28, 2020

--

There is a surprisingly limited number of resources online that detail the process of setting up mapbox-gl and mapbox-gl-directions in a React app (at least for beginners). Uber’s react-map-gl library works well in that it serves as a wrapper for the core Mapbox API, but this library does not include built-in functionality for utilizing the Mapbox Directions API. Displaying routes with this library would require creating custom layers. The Mapbox website has steps for utilizing mapbox-gl in a React app here, but there does not appear to be similar tutorials for the Mapbox Directions API. The majority of tutorials focus on using Mapbox and Mapbox Directions in a static index.html file. For those who are interested in building a React app with Mapbox but unsure how to proceed, this article will serve as a guide for getting started.

React Setup

The first step involves creating a React app. The instructions here demonstrate how to do so. However, with version 8.10 of Node and version 5.6 of npm at a minimum, the following commands will work:

// From the terminalnpx create-react-app your-app-name
cd your-app-name
npm install mapbox-gl @mapbox/mapbox-gl-directions

Next, open the src/App.js file in the your-app-name directory using a familiar text editor. In order to make use of lifecycle methods, change the functional App component to a class component. The component need only return an empty div tag, which will later serve as a container for the map.

// src/App.jsimport React from ‘react’;
import ‘./App.css’;
class App extends React.Component {
render() {
return (
<div />
);
}
}
export default App;

To use the Mapbox and Mapbox Directions APIs, sign up for a Mapbox account here and make note of the newly created public key. To share the app online without exposing this key, create a .env file in the root of the your-app-name directory. Store the key as a variable prefaced with REACT_APP (i.e. REACT_APP_MAPBOX_KEY) in the .env file, and make sure to add the .env file to the .gitignore file.

// From the terminaltouch .env
// .envREACT_APP_MAPBOX_KEY = YOUR_PUBLIC_MAPBOX_KEY
// .gitignore
# files
.env
# dependencies
/node_modules
/.pnp
.pnp.js
...

Integrating Mapbox

Return to the App.js file in the src directory and import mapbox-gl (as mapboxgl) as well as the Mapbox CSS (“mapbox-gl/dist/mapbox-gl.css”). Under the imports, assign the variable in .env that is now storing the Mapbox API key to the built-in mapboxgl.accessToken parameter. The Mapbox key variable from .env is now an environment variable, which is accessible with the “process.env” prefix (i.e. process.env.REACT_APP_MAPBOX_KEY). Now, the foundation is in place to incorporate the map display!

In the componentDidMount lifecycle method, create a new mapboxgl.Map instance with some default parameters:

// src/App.jscomponentDidMount() {

const map = new mapboxgl.Map({
container: this.mapWrapper,
style: 'mapbox://styles/mapbox/streets-v10',
center: [-73.985664, 40.748514],
zoom: 12
});
}

The style, center, and zoom parameters can all be customized to fit various specifications and preferences. The above code’s center parameter has the coordinates of the Empire State Building in New York City, so the middle of the map will focus on the Empire State Building’s location. Please note that this array of coordinates is in a [longitude, latitude] format. For the style parameter, there are a number of options on this page that can change the map display to a dark view or satellite view, for example. Lastly, the zoom parameter determines the degree of magnification on the center location when the map loads. The Mapbox documentation has a list of additional parameters for further customization and functionality options.

The next step involves setting a function with the map’s container value (this.mapWrapper) as the reference attribute of the return statement’s div tag. This div should also have a value for the id or className attribute so that referencing the tag in the stylesheets is possible. Finally, in the App.css file, set the width and height properties for the map. This example includes additional CSS options for the map in the style tags. At this point, the App.js and App.css files should include the following code:

// src/App.css.mapWrapper {
width: 100vw;
height: 100vh;
}
...
// src/App.js
import React from 'react';
import './App.css';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_KEY;class App extends React.Component { componentDidMount() {

const map = new mapboxgl.Map({
container: this.mapWrapper,
style: 'mapbox://styles/mapbox/streets-v10',
center: [-73.985664, 40.748514],
zoom: 12
});
} render() { return (
<div
ref={el => (this.mapWrapper = el)}
className="mapWrapper"
/>
);
}
}export default App;

After running npm start in the terminal, the map should now be visible! The output with the Empire State Building as the center should look like the image below. The map adjusts to the dimensions of the browser window. Users can zoom in and out using the mouse scroll wheel or moving two fingers on a trackpad. By clicking and dragging, users can move across the map or change the map’s focal point.

Integrating Mapbox Directions

The process for incorporating Mapbox Directions is very similar to the above instructions for setting up the core Mapbox API. First, in App.js, import MapboxDirections (from “@mapbox/mapbox-gl-directions/dist/mapbox-gl-directions”) as well as the corresponding CSS (“@mapbox/mapbox-gl-directions/dist/mapbox-gl-directions.css”).

Mapbox Directions comes with its own set of parameters to be aware of. After the core Mapbox object in the componentDidMount, create a new MapboxDirections instance with at least the following parameters:

// src/App.jscomponentDidMount() {...  const directions = new MapboxDirections({
accessToken: mapboxgl.accessToken,
unit: 'metric',
profile: 'mapbox/driving'
})
}

Be sure to reference the public Mapbox key (which is stored in mapboxgl.accessToken) in the new directions object’s accessToken parameter. The unit parameter determines the measurement system used for calculating the distance between two points on the map. The profile parameter adjusts the route, list of directions, and estimated time of arrival based on the user’s mode of transportation. Options for the profile parameter include “mapbox/driving”, “mapbox/walking”, and “mapbox/cycling”. The “mapbox/driving-traffic” extension incorporates past and present traffic data when recommending a driving route. Additional information about these parameters and additional parameter options can be found in the Mapbox Directions API documentation.

For the final step, invoke the addControl method built into Mapbox to add the directions component to the map:

// src/App.jscomponentDidMount() {  const map = new mapboxgl.Map({
container: this.mapWrapper,
style: 'mapbox://styles/mapbox/streets-v10',
center: [-73.985664, 40.748514],
zoom: 12
});
const directions = new MapboxDirections({
accessToken: mapboxgl.accessToken,
unit: 'metric',
profile: 'mapbox/driving'
});
map.addControl(directions, 'top-left');}

The second argument in the addControl method specifies the general position on the map where the directions component will appear. Acceptable positions include “top-right”, “top-left”, “bottom-right”, and “bottom-left”. If addControl is invoked without a second argument, the control defaults to the “top-right” position.

After opening the app in the browser or running npm start in the terminal again, the map will now load with the directions overlay! Users can input a starting point as well as a destination and a route will then populate. Alternatively, users can click two different points on the map to create a route between those points. Changing the directions profile parameter or user mode of transportation is also possible from the map display.

Mapbox offers a multitude of controls beyond directions that developers can use to add additional functionality to their maps. Another example is GeolocateControl. This control adds a button to the map display that, when pressed, centers the map on the user’s location, which is denoted with a pin that dynamically moves when the user changes locations. This page demonstrates how to define a new GeolocateControl instance. This documentation includes instructions for adding pins and markers to the map in general.

Drawbacks and Potential Improvements

This guide provides an effective method of integrating ReactJS, Mapbox, and Mapbox Directions to create a functional map-based app. However, this solution is not without drawbacks. For example, as React continues to transition away from component lifecycle methods and class components in favor of hooks and functional components, this code will certainly need refactoring. If developers are looking to manually create routes by passing the coordinates of specific locations to the map component as props, they will need to consider the React lifecycle. These props may not be accessible in the componentDidMount function, so perhaps another lifecycle method may be more effective in this instance. Lastly, developers should also consider the google-maps-react library. This library is designed to be compatible with React, and it may already include the functionality that fits an app’s specifications.

The completed code from this guide is available in this repo.

--

--

Hi! I am a recent graduate from Fullstack Academy and looking to further develop my skill set professionally as a Full Stack Developer