Skip to main content

Documentation Index

Fetch the complete documentation index at: https://rodrito.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Map Context

The React HERE Maps library uses React Context to share the map instance and HERE Maps objects across components.

Overview

The HereMap component creates a context that provides access to:
  • map - The HERE Maps instance (H.Map)
  • platform - HERE Platform service (H.service.Platform)
  • ui - HERE Maps UI object (H.ui.UI)
  • behavior - Map behavior object (H.mapevents.Behavior)

Using the Context

Built-in Components

All library components automatically consume the context:
import { HereMap, Marker, Polyline, ZoomControl } from '@rodrito/react-here-maps';

<HereMap apikey="YOUR_API_KEY" options={{ center: { lat: 40.7128, lng: -74.0060 }, zoom: 12 }}>
  {/* These components automatically access the map context */}
  <Marker position={{ lat: 40.7128, lng: -74.0060 }} />
  <Polyline points={[...]} />
  <ZoomControl />
</HereMap>

Custom Components

Access the context in your custom components using useMapContext:
import { useMapContext } from '@rodrito/react-here-maps';

function CustomMapComponent() {
  const { map, platform, ui, behavior } = useMapContext();

  // Access the map instance
  useEffect(() => {
    if (map.current) {
      console.log('Map center:', map.current.getCenter());
      console.log('Zoom level:', map.current.getZoom());
    }
  }, [map]);

  return null;
}

Context Values

map (RefObject)

A React ref containing the HERE Maps instance:
const { map } = useMapContext();

// Always check if map is loaded
if (map.current) {
  const center = map.current.getCenter();
  const zoom = map.current.getZoom();
  const bounds = map.current.getViewBounds();
}

platform (RefObject)

Reference to the HERE Platform service for geocoding, routing, etc.:
const { platform } = useMapContext();

if (platform.current) {
  const geocoder = platform.current.getSearchService();
  // Use geocoding services
}

ui (RefObject)

Reference to the HERE Maps UI for controls and popups:
const { ui } = useMapContext();

if (ui.current) {
  // Add custom UI elements
  const bubble = new H.ui.InfoBubble(
    { lat: 40.7128, lng: -74.0060 },
    { content: '<div>Hello World</div>' }
  );
  ui.current.addBubble(bubble);
}

behavior (RefObject)

Reference to map behavior for interaction handling:
const { behavior } = useMapContext();

if (behavior.current) {
  // Disable default behaviors
  behavior.current.disable(H.mapevents.Behavior.Feature.PANNING);
}

Advanced Examples

Map Event Listeners

import { useMapContext } from '@rodrito/react-here-maps';
import { useEffect } from 'react';

function MapEventListener() {
  const { map } = useMapContext();

  useEffect(() => {
    if (!map.current) return;

    const handleMapClick = (evt: H.mapevents.Event) => {
      const coord = map.current!.screenToGeo(
        evt.currentPointer.viewportX,
        evt.currentPointer.viewportY
      );
      console.log('Clicked at:', coord);
    };

    map.current.addEventListener('tap', handleMapClick);

    return () => {
      map.current?.removeEventListener('tap', handleMapClick);
    };
  }, [map]);

  return null;
}

Geocoding Service

import { useMapContext } from '@rodrito/react-here-maps';
import { useState } from 'react';

function Geocoder() {
  const { platform, map } = useMapContext();
  const [result, setResult] = useState<string>('');

  const geocodeAddress = async (address: string) => {
    if (!platform.current) return;

    const service = platform.current.getSearchService();
    service.geocode(
      { q: address },
      (result) => {
        if (result.items.length > 0) {
          const location = result.items[0].position;
          map.current?.setCenter(location);
          setResult(`Found: ${result.items[0].title}`);
        }
      },
      (error) => {
        console.error('Geocoding error:', error);
      }
    );
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Enter address"
        onKeyPress={(e) => {
          if (e.key === 'Enter') {
            geocodeAddress(e.currentTarget.value);
          }
        }}
      />
      {result && <p>{result}</p>}
    </div>
  );
}

Info Bubbles

import { useMapContext } from '@rodrito/react-here-maps';
import { useEffect } from 'react';

function InfoBubbleExample() {
  const { map, ui } = useMapContext();

  const showInfoBubble = (lat: number, lng: number, content: string) => {
    if (!ui.current) return;

    const bubble = new H.ui.InfoBubble(
      { lat, lng },
      {
        content: `<div style="padding: 10px;">${content}</div>`,
      }
    );

    ui.current.addBubble(bubble);
  };

  useEffect(() => {
    if (!map.current) return;

    const handleClick = (evt: H.mapevents.Event) => {
      const coord = map.current!.screenToGeo(
        evt.currentPointer.viewportX,
        evt.currentPointer.viewportY
      );

      showInfoBubble(
        coord.lat,
        coord.lng,
        `<strong>Clicked Location</strong><br/>
         Lat: ${coord.lat.toFixed(4)}<br/>
         Lng: ${coord.lng.toFixed(4)}`
      );
    };

    map.current.addEventListener('tap', handleClick);

    return () => {
      map.current?.removeEventListener('tap', handleClick);
    };
  }, [map, ui]);

  return null;
}

Custom Controls

import { useMapContext } from '@rodrito/react-here-maps';
import { useEffect } from 'react';

function CustomControl() {
  const { map } = useMapContext();

  useEffect(() => {
    if (!map.current) return;

    // Create custom control element
    const controlDiv = document.createElement('div');
    controlDiv.style.position = 'absolute';
    controlDiv.style.top = '10px';
    controlDiv.style.right = '10px';
    controlDiv.style.backgroundColor = 'white';
    controlDiv.style.padding = '10px';
    controlDiv.style.borderRadius = '4px';
    controlDiv.style.boxShadow = '0 2px 4px rgba(0,0,0,0.3)';
    controlDiv.style.cursor = 'pointer';
    controlDiv.textContent = 'Reset View';

    controlDiv.onclick = () => {
      map.current?.setCenter({ lat: 40.7128, lng: -74.0060 });
      map.current?.setZoom(12);
    };

    const mapElement = map.current.getElement();
    mapElement.appendChild(controlDiv);

    return () => {
      controlDiv.remove();
    };
  }, [map]);

  return null;
}

Best Practices

Since context values are refs, always check if they’re loaded before using:
if (map.current) {
  // Safe to use map
}
Always remove event listeners in useEffect cleanup:
useEffect(() => {
  const handler = () => { /* ... */ };
  map.current?.addEventListener('tap', handler);
  return () => {
    map.current?.removeEventListener('tap', handler);
  };
}, [map]);
Use HERE Maps TypeScript definitions for type safety:
const handleEvent = (evt: H.mapevents.Event) => {
  // evt is properly typed
};

See Also

Hooks System

Custom hooks for map functionality

TypeScript

Type-safe development

Components

Available components