Using Mapbox GL JS with React

Build interactive, WebGL-powered maps in React applications with the official react-map-gl library

Introduction

Interactive maps have become essential for modern web applications, from real estate platforms showing property locations to logistics dashboards tracking delivery routes. Mapbox GL JS provides a powerful WebGL-based mapping engine, and when combined with React, creates a seamless development experience that leverages React's component model while maintaining Mapbox's rendering performance.

The react-map-gl library, maintained by the vis.gl community, serves as the official React wrapper for Mapbox GL JS. With its v8.1 release in October 2025, the library has evolved significantly since its initial versions, undergoing a complete rewrite in v7.0 that dramatically improved performance and reduced bundle size from 219k to just 57k.

Building interactive map experiences requires expertise in both frontend development and geographic data visualization. Our web development services team specializes in creating performant, accessible map applications using modern React patterns.

Why react-map-gl?

Key capabilities of the official React wrapper for Mapbox GL JS

Performance Optimized

The v7.0 rewrite reduced bundle size from 219k to 57k while maintaining native Mapbox interaction performance through minimal React overhead.

Full TypeScript Support

Entire codebase written in TypeScript with precise type definitions for all components and props.

Plugin Compatibility

Seamlessly integrate first and third-party plugins like mapbox-gl-draw and mapbox-gl-geocoder.

Dual Provider Support

Choose between Mapbox GL JS or MapLibre GL JS with optimized entry points for each.

Getting Started with react-map-gl

Installation and Environment Setup

Before diving into map implementation, ensure your development environment meets the necessary requirements. The react-map-gl library requires Node.js version 12 or higher and React version 16.3 or later.

For Mapbox users:

npm install react-map-gl mapbox-gl @types/mapbox-gl

For MapLibre users:

npm install react-map-gl maplibre-gl

Since version 8.0, react-map-gl has fully separated its Mapbox and MapLibre implementations, allowing each to have smaller bundle sizes and more precise type definitions.

When working with React applications, understanding modern JavaScript patterns like JavaScript Promises helps manage async map operations and API calls effectively. For applications that need to communicate with backend APIs, following REST API best practices ensures clean, maintainable data integration with your map services.

Basic Map Component Implementation

The core of any react-map-gl implementation is the Map component. This component wraps the underlying WebGL rendering engine while exposing a React-friendly API for configuration and state management.

import React from 'react';
import Map from 'react-map-gl/mapbox';
import 'mapbox-gl/dist/mapbox-gl.css';

function App() {
 return (
 <Map
 mapboxAccessToken="your_mapbox_access_token"
 initialViewState={{
 longitude: -122.4,
 latitude: 37.8,
 zoom: 14
 }}
 style={{ width: 600, height: 400 }}
 mapStyle="mapbox://styles/mapbox/streets-v9"
 />
 );
}

The Map component accepts several key props that control its behavior. The initialViewState prop establishes the map's starting position using longitude, latitude, and zoom level coordinates. The style prop determines the map's dimensions, accepting any valid CSS width and height values.

Understanding ViewState Management

Controlled vs Uncontrolled Components

React developers will find the viewState management familiar territory, as react-map-gl supports both controlled and uncontrolled component patterns. In the uncontrolled pattern, the initialViewState prop sets the starting position, and the map manages its own internal state as users interact with it.

The controlled pattern provides full programmatic control over the map's viewState, enabling scenarios like synchronizing multiple maps, responding to external events, or implementing custom navigation controls.

The v8.1 release introduced Proxy-based camera synchronization that significantly improves how the library handles camera updates between the native controller and React props, particularly when using terrain and non-mercator projections.

This approach to state management aligns with modern React patterns like those used in managing search parameters with Next.js, where controlled state provides flexibility for complex interactions.

Controlled ViewState Pattern
1import { useState, useCallback } from 'react';2import Map, { NavigationControl } from 'react-map-gl/mapbox';3 4function ControlledMap() {5 const [viewState, setViewState] = useState({6 longitude: -122.4,7 latitude: 37.8,8 zoom: 149 });10 11 const handleMoveEnd = useCallback((evt) => {12 setViewState(evt.viewState);13 }, []);14 15 return (16 <Map17 {...viewState}18 onMoveEnd={handleMoveEnd}19 mapboxAccessToken="your_token"20 mapStyle="mapbox://styles/mapbox/streets-v9"21 >22 <NavigationControl position="top-right" />23 </Map>24 );25}

Working with Map Overlays

Markers and Popups

Interactive maps often need to display points of interest, user locations, or other data points overlaid on the map canvas. The react-map-gl library provides several overlay components that integrate seamlessly with the map's coordinate system.

Key overlay components include:

  • Marker: Represents specific geographic points with custom content
  • Popup: Displays contextual information when users interact with markers
  • NavigationControl: Adds zoom buttons and compass
  • GeolocateControl: Integrates with browser geolocation API

When implementing type-safe map components, leveraging TypeScript's advanced features ensures robust code. The new TypeScript compiler features provide improved type inference and faster builds for large map applications.

Popups display contextual information when users interact with markers. The popup component supports various anchor positions and can contain any React content, making it ideal for displaying detailed information about map features.

Building custom interactive components follows patterns similar to fixing React routing loopholes, where component composition and event handling require careful state management.

Markers and Popups Example
1import { useState } from 'react';2import { Marker, Popup, NavigationControl } from 'react-map-gl/mapbox';3 4function MapWithMarkers() {5 const [selectedLocation, setSelectedLocation] = useState(null);6 const locations = [7 { id: 1, name: "Headquarters", longitude: -122.4, latitude: 37.8 },8 { id: 2, name: "Branch Office", longitude: -122.3, latitude: 37.75 }9 ];10 11 return (12 <Map13 initialViewState={{ longitude: -122.4, latitude: 37.8, zoom: 11 }}14 mapboxAccessToken="your_token"15 mapStyle="mapbox://styles/mapbox/streets-v9"16 >17 <NavigationControl position="top-left" />18 19 {locations.map((location) => (20 <Marker21 key={location.id}22 longitude={location.longitude}23 latitude={location.latitude}24 anchor="bottom"25 onClick={(e) => {26 e.originalEvent.stopPropagation();27 setSelectedLocation(location);28 }}29 >30 <div className="custom-marker">📍</div>31 </Marker>32 ))}33 34 {selectedLocation && (35 <Popup36 longitude={selectedLocation.longitude}37 latitude={selectedLocation.latitude}38 anchor="top"39 onClose={() => setSelectedLocation(null)}40 >41 <h3>{selectedLocation.name}</h3>42 </Popup>43 )}44 </Map>45 );46}

Performance Optimization

Minimizing Re-renders

One of the key considerations when building React map applications is managing re-render cycles. The react-map-gl v7.0 rewrite specifically addressed this concern by minimizing React's overhead and offering interaction performance equivalent to the native library.

Optimization strategies:

  • Use React.memo() on child components that interact with the map
  • Implement useMemo() for filtering and transforming location data
  • Consider lazy loading the map component for non-primary features
  • Use controlled vs uncontrolled patterns based on your needs
import { memo, useMemo } from 'react';
import Map, { Marker } from 'react-map-gl/mapbox';

const MapMarker = memo(function MapMarker({ location }) {
 return (
 <Marker longitude={location.longitude} latitude={location.latitude}>
 <div className="marker-icon">{location.icon}</div>
 </Marker>
 );
});

function OptimizedMap({ locations, filters }) {
 const filteredLocations = useMemo(() => {
 return locations.filter(location => filters.includes(location.category));
 }, [locations, filters]);

 return <Map>{/* ... */}</Map>;
}

Performance optimization in map applications shares principles with optimizing V8 compiler performance--understanding the underlying engine and structuring code to minimize overhead. This approach mirrors techniques explored in our guide on optimizing JavaScript V8 compiler efficiency.

Advanced Features and Ecosystem

Map Layers and Sources

For applications requiring custom data visualization, react-map-gl provides direct access to Mapbox's layer and source system. Sources define where data comes from--whether tiled datasets, GeoJSON files, or vector tiles--while layers determine how that data is visually represented.

Third-Party Plugin Integration

The react-map-gl architecture allows seamless integration with first and third-party plugins designed for Mapbox GL JS. Popular plugins like mapbox-gl-draw for creating custom shapes and mapbox-gl-geocoder for address search integrate without modification. Creating custom map overlays shares conceptual similarities with building custom directives in Vue.js, where you extend the framework's capabilities with reusable behavior.

This plugin ecosystem extends the library's capabilities far beyond basic mapping, enabling complex applications like property mapping tools, delivery route planners, and geographic data collection systems.

When building complex React applications with maps, understanding component patterns from our React 19 guide and component styling approaches from styled-components best practices helps create maintainable codebases.

CSS Styling Requirements

Including the Stylesheet

The Mapbox and MapLibre base libraries require their respective stylesheets to be loaded for proper rendering of map tiles, controls, and other visual elements.

Import directly in JavaScript:

import 'mapbox-gl/dist/mapbox-gl.css';

Or include in HTML:

<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css" rel="stylesheet" />

Finding your installed version requires running npm ls mapbox-gl to ensure the stylesheet version matches your installed library version.

Proper CSS integration ensures map tiles, controls, and UI elements render correctly across different browsers and screen sizes.

Conclusion

Integrating Mapbox GL JS with React through the react-map-gl library provides a powerful combination for building interactive mapping applications. The library's evolution--from its initial versions through the significant v7.0 rewrite to the current v8.1 release--demonstrates a sustained commitment to performance optimization and developer experience.

Whether you're building a simple location display or a complex geographic data visualization platform, react-map-gl provides the flexibility and performance needed for modern web mapping applications. The combination of WebGL-powered rendering, React's component model, and extensive plugin ecosystem makes it a compelling choice for any project requiring interactive maps.

Our team has experience building map-powered applications for real estate platforms, logistics systems, and location-based services. Contact our web development team to discuss how we can help implement interactive mapping solutions for your project.

Frequently Asked Questions

Ready to Build Interactive Maps?

Our team specializes in creating performant, accessible map experiences for web applications.