Mapbox with React

displaying a customized map on our (React) websites
2025-05-22 12:26 // updated 2025-05-22 14:35

Mapbox allows us to display a customized map on our own websites, provided that we have the following:

In this page, we will review how to:

  • Setup (our folder and file system)
  • Create our HTML index file
  • Create our React front-end logic file
  • Initialize the Mapbox API key
  • Configure our map defaults
  • Style the map
  • Housekeeping with Git
  • Run the map

Setup

In Terminal, let's go to our project folder:

  • npm init to create a package.json file at the project root
  • mkdir public to create a folder for the final product with the following files:
    • index.html for the web app
    • index.css for the web app's styles
  • mkdir src in the root to create the app front-end:
    • index.js for all the React

Still in the Terminal, in the project root, we will install our dependencies:

npm install mapbox-gl react react-dom react-scripts worker-loader

Check if the package.json looks something like this:

{
  "name": "(project name)",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "keywords": [
    "mapbox", "react", "maps", "cartography", "geospatial"
  ],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "mapbox-gl": "^3.12.0",
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-scripts": "^5.0.1",
    "worker-loader": "^3.0.8"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Creating the HTML index file

Let's go to public/index.html to setup our minimal map interface:

<!DOCTYPE html>
<html lang="en">

  <head>

    <title>our mappy</title>
    
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

  </head>

  <body>
  
    <div id="app"></div>
  
  </body>

</html>

Creating the React front-end logic

Let's go to src/index.js to create our foundational React file:

import React from "react"
import ReactDOM from "react-dom"
import "mapbox-gl/dist/mapbox-gl.css"
import "./index.css"
import App from "./App"

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("app")
)

Unpacking the above:

  • the first and second lines deal with React
  • the third line deals with the Mapbox styling library
  • the line with index.css contains our own styling in the src folder
  • the line with App contains our App logic
  • finally, we have our app as the remainder of the file

React will populate the code in App inside the index.html div tag with the id of app!

Initializing the Mapbox API key

Now that we have our React Mapbox workspace setup, we will move into the App.js file:

import React, { useRef, useEffect, useState } from "react"

import mapboxgl from "!mapbox-gl" 
// eslint-disable-line import/no-webpack-loader-syntax

function App() {
  mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_KEY
  return <div ref={mapContainer} className="map-container" />
}

export default App

Before we use that file, we should create an .env file in the project's root folder, containing the following:

REACT_APP_MAPBOX_KEY=(YOUR_API_KEY_HERE)

(Of course, we should replace everything after the equals sign with our actual API key!)

Going back to the App.js file, we can see that we access this variable with:

process.env.REACT_APP_MAPBOX_KEY

Configuring the map defaults

We still have to give our map its default values for geographical coordinates, (latitude and longitude), zoom level, etc.

We shall then kick-start our map, again in src/App.js:

import React, { useRef, useEffect, useState } from "react"

import mapboxgl from "!mapbox-gl" 
// eslint-disable-line import/no-webpack-loader-syntax

function App() {

  // our key to "the city"
  mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_KEY

  // defining our container and content (i.e. the map)
  const mapContainer = useRef(null)
  const map = useRef(null)

  // variables for the map (location and zoom level)
  const myLongitude = -79.3832
  const myLatitude = 43.6532
  const myZoomLevel = 9
  const [lng, setLng] = useState(myLongitude)
  const [lat, setLat] = useState(myLatitude)
  const [zoom, setZoom] = useState(myZoomLevel)

  // what happens when the app loads or those variables change
  useEffect(() => {
    if (map.current) return 
    map.current = new mapboxgl.Map({
      container: mapContainer.current,
      style: "mapbox://styles/mapbox/standard",
      center: [lng, lat],
      zoom: zoom
    })
  })

  return <div ref={mapContainer} className="map-container" />
  
}

export default App

In the above, we implemented two things:

  • a useEffect hook that ensures the rendering happens anytime the state changes
  • a return statement that will provide a container for the map
    recall the useRef hook at the top of the Map functional component

Styling the map

Lastly, we just need to add some minimal CSS in src/index.css:

.map-container {
  position: absolute;
  top: 0; right: 0; left: 0; bottom: 0
}

This would make the map take up the entirety of its parent container, however big that might be (could be "full screen" or could just take up part of the webpage!)

Housekeeping with Git

With GIt, we will need to add a .gitignore file in the project root with the following:

node_modules
.env

(This will keep the project light and safe!)

Running the map

Okay, let's test the map!

In Terminal, let's go into the project folder and start the app:

npm start

When we see a message that says "Compiled successfully!" we can then:

  • take note of the "localhost" address
  • go to the browser and use that address to see the map!
⬅️ older (in snippets)
🧑🏻‍💻 JavaScript "object arithmetic"
⬅️ older (in code)
🔡 Code as total algebra
⬅️ older (posts)
🛳️ What to consider for a cruise?