EliasGeoDev
Volver al blog
Web GIS / MapLibre

Construyendo un mapa con
MapLibre GL JS + React

En este tutorial vamos a crear desde cero una pequeña aplicación web capaz de mostrar un mapa interactivo utilizando React y MapLibre GL JS.

ReactViteMapLibre GL JSpnpm
01

Crear el proyecto

Lo primero que vamos a hacer es crear una nueva aplicación de React utilizando Vite.

Abre una terminal en tu computadora. No necesitas crear ninguna carpeta manualmente. Vite se encargará de crearla por nosotros.

bash
pnpm create vite@latest maplibre-react-app --template react

Cuando termine el proceso, tendrás una nueva carpeta llamada:

maplibre-react-app

Dentro de esa carpeta estarán los archivos iniciales que Vite necesita para arrancar nuestra aplicación.

02

Entrar al proyecto

Ahora que la carpeta existe, necesitamos entrar en ella desde la terminal.

bash
cd maplibre-react-app

A partir de este momento, los comandos que ejecutemos estarán dentro de nuestro proyecto.

Importante: asegúrate de estar dentro de maplibre-react-app antes de continuar.
03

Instalar las dependencias

Vite ya creó nuestro proyecto, pero todavía tenemos que instalar las dependencias que necesita React.

Desde la carpeta raíz del proyecto ejecuta:

bash
pnpm install

Este comando descargará e instalará los paquetes que el proyecto necesita para funcionar.

Dependiendo de tu conexión, puede tardar unos segundos.

04

Instalar MapLibre GL JS

Ahora vamos a instalar MapLibre GL JS.

MapLibre será el encargado de mostrar nuestro mapa interactivo dentro de la aplicación.

bash
pnpm add maplibre-gl

Cuando termine la instalación, MapLibre estará disponible para utilizarlo dentro de nuestro proyecto.

05

Ejecutar el proyecto

Antes de comenzar a modificar archivos, vamos a comprobar que nuestra aplicación funciona.

Ejecuta:

bash
pnpm dev

La terminal debería mostrar una dirección local parecida a:

http://localhost:5173/

Copia esa dirección y ábrela en tu navegador.

Si aparece la página inicial de Vite + React, significa que nuestro proyecto está funcionando correctamente.

06

Preparar la estructura

Antes de comenzar a escribir el código del mapa vamos a ordenar un poco nuestro proyecto.

Dentro de la carpeta src vamos a crear tres carpetas:

Estructura
src/
├── components/
├── context/
└── hooks/

No necesitas memorizar para qué sirve cada carpeta. Durante el tutorial iremos viendo qué colocamos en cada una.

07

Crear el contexto del mapa

Dentro de la carpeta:

src/context/

crea un archivo llamado:

MapContext.jsx

Copia dentro de ese archivo:

jsx
// src/context/MapContext.jsx

import { createContext, useContext, useState, useRef } from "react";

const MapContext = createContext(null);

export function MapProvider({ children }) {
  const mapRef = useRef(null);
  const [isMapReady, setIsMapReady] = useState(false);

  return (
    <MapContext.Provider
      value={{
        mapRef,
        isMapReady,
        setIsMapReady,
      }}
    >
      {children}
    </MapContext.Provider>
  );
}

export const useMapInstance = () => {
  const context = useContext(MapContext);
  if (!context) {
    throw new Error("useMapInstance debe usarse dentro de un MapProvider");
  }
  return context;
};

Este archivo será el lugar donde mantendremos disponible nuestra instancia del mapa para que otros componentes puedan utilizarla.

08

Crear el hook para acceder al mapa

Ahora vamos a crear una pequeña herramienta que nos permita acceder fácilmente al mapa desde otros componentes.

Entra en:

src/hooks/

y crea un archivo llamado:

useMap.js
javascript
// src/hooks/useMap.js

import { useEffect } from "react";
import * as maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
import { useMapInstance } from "../context/MapContext";

const OSM_STYLE = {
  version: 8,
  sources: {
    "osm-tiles": {
      type: "raster",
      tiles: [
        "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
        "https://b.tile.openstreetmap.org/{z}/{x}/{y}.png",
        "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png",
      ],
      tileSize: 256,
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    },
  },
  layers: [
    {
      id: "osm-tiles-layer",
      type: "raster",
      source: "osm-tiles",
      minzoom: 0,
      maxzoom: 19,
    },
  ],
};

export const useMap = (containerRef) => {
  const { mapRef, isMapReady, setIsMapReady } = useMapInstance();

  useEffect(() => {
    if (!containerRef.current || mapRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: OSM_STYLE, 
      center: [-3.70379, 40.416775], 
      zoom: 12,
    });

    mapRef.current = map;

    const handleLoad = () => {
      setIsMapReady(true);
    };

    if (map.isStyleLoaded()) {
      setIsMapReady(true);
    } else {
      map.once("load", handleLoad);
    }

    return () => {
      map.off("load", handleLoad);
      map.remove();
      mapRef.current = null;
      setIsMapReady(false);
    };
  }, [containerRef, mapRef, setIsMapReady]);

  return { map: mapRef.current, isMapReady };
};

Con esto podremos acceder al mapa desde nuestros componentes sin tener que repetir toda la lógica que acabamos de crear.

09

Crear nuestro mapa

Ahora viene la parte importante: vamos a crear el componente que realmente mostrará el mapa.

Dentro de:

src/components/

crea:

MainMap.jsx

Ahora copia el siguiente código:

jsx
// src/components/MainMap.jsx

import { useRef } from "react";
import { useMap } from "../hooks/useMap";

export const MainMap = () => {
  const mapContainerRef = useRef(null);

  const { isMapReady } = useMap(mapContainerRef);

  return (
    <div style={{ position: "relative", width: "100vw", height: "100vh" }}>
      {!isMapReady && (
        <div
          style={{
            position: "absolute",
            top: 10,
            left: 10,
            zIndex: 1,
            background: "rgba(0,0,0,0.7)",
            color: "white",
            padding: "8px 12px",
            borderRadius: "4px",
          }}
        >
          Cargando mapa...
        </div>
      )}

      <div ref={mapContainerRef} style={{ width: "100%", height: "100%" }} />
    </div>
  );
};

En este componente estamos creando el mapa y estableciendo su ubicación inicial.

En este ejemplo utilizamos Madrid como ubicación inicial:

Longitud

-3.70379

Latitud

40.416775

10

Configurar CSS estilo inicial del mapa

Dentro del archivo index.css, reemplaza todo el contenido por el siguiente código:

Dentro de:

src/index.css
jsx
// src/index.css
html,
body,
#root {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

Es necesario reemplazar este CSS porque las reglas originales (como el ancho fijo de 1126px, el alineado centrado y la propiedad display: flex en #root) comprimen el contenedor a un alto de 0px y desalinean el canvas, impidiendo que el mapa se renderice a pantalla completa.

11

Integrar todas las piezas

Ya tenemos todas las partes necesarias. Solo falta conectarlas.

Abre:

src/App.jsx

Reemplaza su contenido por:

jsx
// src/App.jsx

import { MapProvider } from "./context/MapContext";
import { MainMap } from "./components/MainMap";

function App() {
  return (
    <MapProvider>
      <MainMap />
    </MapProvider>
  );
}

export default App;

Guarda los cambios y vuelve al navegador.

¡Ya tienes tu primer mapa!

Ahora deberías poder visualizar el mapa interactivo y utilizar los controles de navegación. Si prefieres no hacer el paso a paso, puedes descargar el repositorio completo aquí.

Siguiente

Agregar fuentes de datos y capas

Una vez que el mapa básico funciona, podemos comenzar a trabajar con fuentes de datos reales y construir nuestra aplicación geoespacial.