After taking a look to mapbox documentation, I wrote this component
import React from "react";
import mapboxgl from "mapbox-gl";
import "./Map.css";
mapboxgl.accessToken = "...";
type Props = {
longitude: number;
latitude: number;
};
class Map extends React.Component<Props> {
private mapContainer: any;
private map: any;
componentDidMount(): void {
this.map = new mapboxgl.Map({
container: this.mapContainer,
center: [this.props.longitude, this.props.latitude],
style: "....",
zoom: 13
});
}
render(): JSX.Element {
return (
<div
ref={(el): void => {
this.mapContainer = el;
}}
className="mapContainer"
/>
);
}
}
export default Map;
This code works correctly, however, in my real project, we are using TypeScript. I don't want to use any
for mapContainer
and map
.
I have imported "@types/mapbox-gl": "^1.7.0",
into my project, but I cannot figure out what type I have to use here.
My tries until now:
private map:mapboxgl.Map
. It seems to be correct, but then it complais because it is not initialized on the constructor. According to mapbox documentation it has to be initialize on componentDidMount
. I can type the variable with mapboxgl.Map | null
. But then i have to check constally to not be null, to remove
some annoying warnings.private mapContainer = React.userRef<HtmlElement>(null);
. But then, when i try to initialize the map, it says Type 'RefObject<HTMLElement>' is not assignable to type 'string | HTMLElement'.
Any ideas?
Based upon your code, the following works. First, you need to import the Map
type which get's exported from mapbox-gl
:
import mapbox-gl, { Map } from "mapbox-gl";
Which later can be used as a type for the map inside your component:
private map: Map | undefined; // | undefined is needed here otherwise Typescript will complain about a missing initialiser inside the constructor.
Now comes the tricky part, container is defined as:
container: string | HTMLElement
inside the MapboxOptions type definition. Therefore we have to workaround it a little bit:
class SampleMap extends React.Component<Props> {
private mapContainer: HTMLElement | null | undefined = undefined;
private map: Map | undefined;
componentDidMount(): void {
this.map = new mapboxgl.Map({
container:
this.mapContainer === undefined || this.mapContainer === null
? "" // or pass in some other HTMLElement which is definitely defined or similar ...
: this.mapContainer,
... // abbreviated
});
}
render(): JSX.Element {
... // abbreviated
}
}
There a check if the mapContainer
is defined and not null and pass in the mapContainer
otherwise a string
or maybe you could pass in some other HTMLElement
which you know is 100% defined. E.g. document#root
.
Complete code can be found here: on CodeSandbox