This component wraps a MapLibre Layer 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
.
The id
and the type
props are readonly. This allows us to manage
reactivity on the same instance throughout its lifecycle. In some cases you'll have
to add a key
prop to maintain this state. see below Error: RLayer id should not change.
import { RMap, RSource, RLayer } from "maplibre-react-components";
const townPaintStyle = {
"fill-outline-color": "rgba(0,0,0,0.1)",
"fill-color": "rgba(255,0,0,0.3)",
};
export default function App() {
return (
<RMap>
<RSource id="thyez" type="geojson" data="/data/thyez.geojson" />
<RLayer
source="thyez"
id="thyez-fill"
type="fill"
paint={townPaintStyle}
/>
</RMap>
);
};
Some props are reactives. Here is the complete list, it applies depending on whether or not the layer has this prop in its options.
type LayerReactiveOptions = {
layout?: any;
paint?: any;
filter?: FilterSpecification;
minzoom?: number;
maxzoom?: number;
beforeId?: string;
}
Be careful to define stable objects for layout
, paint
and filter
props to avoid multiplying renderings.
import { RLayer, RMap, RSource } from "maplibre-react-components";
import { useMemo, useState } from "react";
const center = { lng: 6.53, lat: 46.09 };
export default function App() {
const [red, setRed] = useState(false);
const townPaintStyle = useMemo(
() => ({
"fill-outline-color": "rgba(0,0,0,0.1)",
"fill-color": red ? "rgba(255,0,0,0.3)" : "rgba(0,0,0,0.3)",
}),
[red],
);
return (
<>
<RMap
minZoom={12}
initialCenter={center}
mapStyle="https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json"
>
<RSource id="thyez" type="geojson" data="/data/thyez.geojson" />
<RLayer
source="thyez"
id="thyez-fill"
type="fill"
paint={townPaintStyle}
/>
</RMap>
<div className="absolute right-4 top-4">
<button onClick={() => setRed((r) => !r)}>
{red ? "set Gray" : "set Red"}
</button>
</div>
</>
);
}
With MapLibre we can listen to map events associated to specific layer. See MapLibre doc reference MapLayerEventType.
// Initialize the map
let map = new Map({ /* map options */ });
// Set an event listener for a specific layer
map.on('the-event-name', 'poi-label', (e) => {
console.log('An event has occurred on a visible portion of the poi-label layer');
});
With MapLibre React Components, you define these listeners directly as props of your <RLayer />
.
import { MapLayerMouseEvent } from "maplibre-gl";
import { RMap, RLayer } from "maplibre-react-components";
export default function App() {
function handleClick(e: MapLayerMouseEvent) {
// your logic
}
return (
<RMap>
<RLayer
onClick={handleClick}
source="thyez"
id="thyez-fill"
type="fill"
/>
</RMap>
);
};
When you have conditional renderers within your RMap
component you will need to set the
prop key
for your RLayer
to help React maintain its association with the correct component.
Consider id
prop for MapLibre mapping and key
prop for React mapping. If you want to know
why see Tips: key vs id.
RLayer
accept same props as Layer
options plus beforeId
. Check the MapLibre Layers reference page for details.
import { CustomLayerInterface, LayerSpecification } from "maplibre-gl";
type RLayerProps = LayerOptions & LayerCallbacks & {
beforeId?: string;
};
type LayerOptions = LayerSpecification | CustomLayerInterface;
import { MapLayerMouseEvent, MapLayerTouchEvent } from "maplibre-gl";
export type LayerCallbacks = {
onMouseDown?: (e: MapLayerMouseEvent) => void;
onMouseUp?: (e: MapLayerMouseEvent) => void;
onMouseOver?: (e: MapLayerMouseEvent) => void;
onMouseOut?: (e: MapLayerMouseEvent) => void;
onMouseMove?: (e: MapLayerMouseEvent) => void;
onMouseEnter?: (e: MapLayerMouseEvent) => void;
onMouseLeave?: (e: MapLayerMouseEvent) => void;
onClick?: (e: MapLayerMouseEvent) => void;
onDblClick?: (e: MapLayerMouseEvent) => void;
onContextMenu?: (e: MapLayerMouseEvent) => void;
onTouchStart?: (e: MapLayerTouchEvent) => void;
onTouchEnd?: (e: MapLayerTouchEvent) => void;
onTouchCancel?: (e: MapLayerTouchEvent) => void;
onTouchMove?: (e: MapLayerTouchEvent) => void;
};