RMarker

This component wraps a MapLibre Marker object. He manages its life cycle and is responsible for adding/removing it to the map. For this reason this component must be a descendant of RMap.

Usage

import { RMap, RMarker } from "maplibre-react-components";
import CustomMarker from "./CustomMarker";
 
const center: [number, number] = [-0.5, 47.5];
 
export default function App() {
  return (
    <RMap initialCenter={center}>
      <RMarker longitude={-2.5} latitude={55} />
 
      {/* with custom Element */}
      <RMarker longitude={19} latitude={53.6} initialAnchor="bottom">
        <CustomMarker />
      </RMarker>
    </RMap>
  );
}
 

If you use a custom marker element don't forgot to memoize the component.

// CustomMarker.tsx
import { memo } from "react";
 
// https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.
const ICON = `M215.7 499.2C267 435 384 279.4 384 192C384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2c12.3 15.3 35.1 15.3 47.4 0zM192 128a64 64 0 1 1 0 128 64 64 0 1 1 0-128z`;
 
function CustomMarker() {
  return (
    <svg
      height={30}
      viewBox="0 0 384 512"
      style={{ cursor: "pointer", fill: "#DBA726" }}
    >
      <path d={ICON} />
    </svg>
  );
}
export default memo(CustomMarker);

Draggable controlled component

If your marker component is draggable, you need to register a handler for the dragend or drag event to update the state.

import { type Marker } from "maplibre-gl";
import { Event, RMap, RMarker } from "maplibre-react-components";
import { useCallback, useState } from "react";
 
const center: [number, number] = [-0.5, 47.5];
 
export default function App() {
  const [markerCoords, setMarkerCoords] = useState(center);
 
  const handleDragEnd = useCallback((e: Event<Marker>) => {
    setMarkerCoords(e.target.getLngLat().toArray());
  }, []);
 
  return (
    <RMap initialCenter={center} initialZoom={2}>
      {/* controlled marker */}
      <RMarker
        longitude={markerCoords[0]}
        latitude={markerCoords[1]}
        draggable={true}
        onDragEnd={handleDragEnd}
      />
      <div className="absolute bottom-4 left-4 rounded-2xl bg-gray-0 p-4">
        Marker position : {markerCoords.map(Math.round).join(", ")}
      </div>
    </RMap>
  );
}
 

Reference

Check the MapLibre MarkerOptions reference page for details of MarkerInitialOptions and MarkerReactiveOptions.

type RMarkerProps =
  {
    longitude: number;
    latitude: number;
    /**
     * for custom element
     */
    children?: ReactNode;
  } &
 
  /**
   * Non reactive marker options (only used during instantiation)
   * prefixed with "initial" + first letter uppercase
   */
  MarkerInitialOptions &
 
 
  /**
   * Reactive marker options.
   * they have the same name as in MarkerOptions
   */
  MarkerReactiveOptions &
 
 
  /**
   * Listenners for marker events
   * prefixed with "on" + first letter uppercase
   */
  MarkerCallbacks;
type MarkerInitialOptions = {
  initialAnchor?: PositionAnchor;
  initialColor?: string;
  initialScale?: number;
};
type MarkerReactiveOptions = {
  className?: string;
  offset?: PointLike;
  draggable?: boolean;
  clickTolerance?: number;
  rotation?: number;
  rotationAlignment?: Alignment;
  pitchAlignment?: Alignment;
  opacity?: string;
  opacityWhenCovered?: string;
  subpixelPositioning?: boolean; // v4.5.1+
};
type MarkerCallbacks = {
  onDragStart?: (e: Event<Marker>) => void;
  onDrag?: (e: Event<Marker>) => void;
  onDragEnd?: (e: Event<Marker>) => void;
 
  // native DOM event
  onClick?: (e: MouseEvent) => void;
}