Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the correct types to map variables using Mapbox in React?

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?

like image 610
Rumpelstinsk Avatar asked Oct 30 '25 02:10

Rumpelstinsk


1 Answers

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

like image 84
r3dst0rm Avatar answered Nov 01 '25 14:11

r3dst0rm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!