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
npm install @maimaps/react maplibre-glRequires 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.
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>
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()
useMaimaps(): MaimapsClientGet 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>
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>
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>
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>
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
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()
useSearch(): MaimapsAsyncResult<SearchParams, SearchResult[]>Free-text search. Safe to call on every keystroke.
useRoute()
useRoute(): MaimapsAsyncResult<RouteParams, RouteResult>A-to-B routing. For waypoints or loccode endpoints, reach for useMaimaps() and call client.routeAdvanced().
useReverseGeocode()
useReverseGeocode(): MaimapsAsyncResult<ReverseGeocodeParams, ReverseGeocodeResult>Coordinate to address. Pairs naturally with MaimapsMap's onClick.
usePointDetails()
usePointDetails(): MaimapsAsyncResult<PointDetailsParams, PointDetails>Tapped-point resolution, for long-press and dropped-pin flows.
useMaimapsMap()
useMaimapsMap(): maplibregl.Map | nullGet 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.