@maimaps/react · v0.1.1 · Beta

Maimaps React SDK

React bindings over the JS core — MaimapsProvider, MaimapsMap, Marker, RoutePolyline, and hooks for search, routing, and geocoding.

Package

@maimaps/react

Version

v0.1.1

Registry

npm

Platforms

React 18+ • Browser

Requires

maplibre-gl ^5, react >=18, react-dom >=18

Status

Beta — 0.x, minors may break

Overview

Component and hook bindings on top of @maimaps/js, with maplibre-gl as a peer dependency. The provider injects your API key into every map resource request; useSearch, useRoute, useReverseGeocode, and usePointDetails cover the REST surface and drop stale responses automatically. The entire @maimaps/js surface is re-exported, so you only need one import.

Every endpoint this SDK wraps is documented, with request parameters and response bodies, in the Maimaps API reference. This page documents the SDK surface itself.

Install

Terminal
npm install @maimaps/react maplibre-gl

Requires maplibre-gl ^5, react >=18, react-dom >=18, which you install yourself as peer dependencies.

Quickstart

Replace mk_test_your_key with a MAIMAPS key from the console. Keys are mk_live_… for LIVE and mk_test_… for TEST; nothing else in your code changes between the two.

App.tsx
import { MaimapsProvider, MaimapsMap, useSearch } from "@maimaps/react";

function SearchBox() {
  const { execute, data, loading } = useSearch();

  return (
    <>
      <input
        placeholder="Search places…"
        onChange={(e) =>
          execute({ q: e.target.value, latitude: 9.0579, longitude: 7.4951 })
        }
      />
      {loading && <p>Searching…</p>}
      <ul>
        {data?.map((r) => (
          <li key={r.id}>{r.name} — {r.loccode}</li>
        ))}
      </ul>
    </>
  );
}

export default function App() {
  return (
    <MaimapsProvider apiKey="mk_test_your_key">
      <MaimapsMap styleMode="dark" center={[7.4951, 9.0579]} zoom={12} />
      <SearchBox />
    </MaimapsProvider>
  );
}

Provider & client access

@maimaps/react re-exports the whole of @maimaps/js, so every type, error, and utility documented on the JS SDK page is importable from here too.

<MaimapsProvider>

Signature
interface MaimapsProviderProps {
  apiKey?: string;
  environment?: 'staging' | 'production';
  apiBaseUrl?: string;
  mapBaseUrl?: string;
  client?: MaimapsClient;    // supply a pre-built client instead of apiKey
  children?: ReactNode;
}

Wrap your app once. It constructs a MaimapsClient and hands it to every hook and map component below. Pass client instead of apiKey when you want to share one instance with non-React code.

useMaimaps()

Signature
useMaimaps(): MaimapsClient

Get the client from context, for endpoints with no dedicated hook (loccodes, place categories) or for calls outside render. Throws if used outside a MaimapsProvider.

Map components

Thin, declarative wrappers over maplibre-gl, which is a peer dependency you install yourself.

<MaimapsMap>

Signature
interface MaimapsMapProps {
  styleFamily?: string;
  styleMode?: 'light' | 'dark';
  center?: LngLatLike;        // [lng, lat] — MapLibre order
  zoom?: number;
  onClick?: (event: MapMouseEvent) => void;
  onLoad?: (map: maplibregl.Map) => void;
  mapLibreOptions?: Omit<MapOptions, 'container' | 'style' | 'transformRequest'>;
  wordmarkPosition?: 'bottom-left' | 'top-left' | 'top-right' | 'bottom-right';
  className?: string;
  style?: CSSProperties;
  children?: ReactNode;
}

// Ref handle
interface MaimapsMapHandle { getMap(): maplibregl.Map | null }

The map. Loads the keyed style and wires key injection for tiles, sprites, and glyphs automatically. Note center is [lng, lat], MapLibre's order, not the API's. Drop to the raw MapLibre instance via a ref (getMap()) or the onLoad callback when you need something the props do not cover.

<Marker>

Signature
interface MarkerProps {
  longitude: number;
  latitude: number;
  children?: ReactNode;
}

A pin at a coordinate. Children become the marker's content, so you can render arbitrary JSX instead of the default pin.

<RoutePolyline>

Signature
interface RoutePolylineProps {
  coordinates: ReadonlyArray<readonly [number, number]>;   // [lng, lat] pairs
  color?: string;   // default '#2563eb'
  width?: number;   // default 4
  id?: string;
}

Draw a decoded route on the map. coordinates are [longitude, latitude] pairs, which is the opposite of what decodePolyline returns: flip with .map(([lat, lng]) => [lng, lat]).

<UserLocation>

Signature
interface UserLocationProps {
  follow?: boolean;
  autoStart?: boolean;
  showAccuracyCircle?: boolean;
  position?: ControlPosition;
  onLocate?: (position: GeolocationPosition) => void;
  onError?: (error: GeolocationPositionError) => void;
}

Show and optionally follow the user's position, using the browser Geolocation API. Handle onError: users deny location permission routinely.

Hooks

Four async hooks cover the REST surface. They share one shape, they never fire on mount (you call execute), and each drops stale responses via a sequence token, so typing fast into a search box cannot render an out-of-order result.

The shared result shape

Signature
interface MaimapsAsyncResult<TParams, TData> {
  data: TData | null;
  error: Error | null;
  loading: boolean;
  execute: (params: TParams) => Promise<TData | undefined>;
}

Every hook below returns this. execute resolves with the data as well as setting it on the hook, so you can await it inline when that reads better.

useSearch()

Signature
useSearch(): MaimapsAsyncResult<SearchParams, SearchResult[]>

Free-text search. Safe to call on every keystroke.

useRoute()

Signature
useRoute(): MaimapsAsyncResult<RouteParams, RouteResult>

A-to-B routing. For waypoints or loccode endpoints, reach for useMaimaps() and call client.routeAdvanced().

useReverseGeocode()

Signature
useReverseGeocode(): MaimapsAsyncResult<ReverseGeocodeParams, ReverseGeocodeResult>

Coordinate to address. Pairs naturally with MaimapsMap's onClick.

usePointDetails()

Signature
usePointDetails(): MaimapsAsyncResult<PointDetailsParams, PointDetails>

Tapped-point resolution, for long-press and dropped-pin flows.

useMaimapsMap()

Signature
useMaimapsMap(): maplibregl.Map | null

Get the underlying MapLibre instance from inside a MaimapsMap child. Returns null until the map has loaded.

Resources

This SDK is 0.1.0 and in beta. Breaking changes can land in minor versions until 1.0.0, so pin the version if you need stability.