react-map-gl-geocoder icon indicating copy to clipboard operation
react-map-gl-geocoder copied to clipboard

Can Not Use react.map.gl.gecoder with Typescript

Open LAYTHJABBAR opened this issue 4 years ago • 4 comments

Hello Team,

I have tried a lot to use the gecoder with type script but it is keep showing errors my file is as below

import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import React, { useRef } from 'react';
import ReactMapGL, { Marker } from 'react-map-gl';
import Geocoder from 'react-map-gl-geocoder';
import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css';
import DropoffPinWithLayer from '../../pages/Routing/Components/Pins/dropoffWithLayer';
import './map.scss';
import { IMap } from './type';

const Map = ({ 
  customerToMark, 
  customerToZoom, 
  isSearchOutOfMap, 
  itsDraggable, 
  geocoder, 
  handleOnDragEnd, 
  handleOnResult, 
  handleOnClear,
  handleOnClickEnd,
  handleViewportChange,
  height,
  marker, 
  position,
  radius,
  width,
  viewport,
}: IMap) => {
  let ZoomCustomer: React.ReactNode, MarkeAllCustomers: React.ReactNode, GeocoderTag: React.ReactNode, SearchBarRefrence: React.ReactNode;
  const geocoderContainerRef: any = useRef();
  const mapRef: any = useRef();
 
   if(isSearchOutOfMap === true) {
    SearchBarRefrence = (<div ref={geocoderContainerRef} />);
   }

  if (geocoder == true) {
    GeocoderTag = (
      <Geocoder
        containerRef={geocoderContainerRef}
        mapRef={mapRef}
        mapboxApiAccessToken={mapboxgl.accessToken}
        position={position}
        onResult={handleOnResult}
        ReverseGeoCode={true}
        onClear={handleOnClear}
      />
    );
  }
  if (customerToZoom == true) {
    ZoomCustomer = (
      <Marker latitude={customerToMark.lat} longitude={customerToMark.lon} >
        {marker}
      </Marker>
    );
  }
  if (customerToZoom == true && itsDraggable === true) {
     
    ZoomCustomer = (
      <DropoffPinWithLayer
        location={ customerToMark }
        onDragEnd={handleOnDragEnd}
        radius={radius}
      />
    );
  }

  return (
    <div>
      {SearchBarRefrence}
      <ReactMapGL
        {...viewport}
        ref={mapRef}
        width={width}
        onClick={(event) => {
          handleOnClickEnd(event)
        }}
        height={height}
        onViewportChange={handleViewportChange}
        mapboxApiAccessToken={mapboxgl.accessToken}
        mapStyle="mapbox://styles/mapbox/outdoors-v11"
      >
        {ZoomCustomer}
        {MarkeAllCustomers}
        {GeocoderTag}
      </ReactMapGL>
    </div>
  );
};

export default Map;

the Error messages that I am getting are TypeError: Cannot read property 'remove' of undefined && TypeError: Cannot read property 'addControl' of null

is there a way to fix that

LAYTHJABBAR avatar Feb 05 '21 17:02 LAYTHJABBAR

I was having the same issue but I am not using TypeScript.

It appears react-map-gl-geocoder v2.1.6 is not compatible with the latest versions of react-map-gl v6.1.x

react-map-gl v6.1.0-alpha introduces a breaking change somewhere.

Switching to react-map-gl v6.0.3 works for me. I am also using the latest version of react.

react-map-gl-geocoder

icebox avatar Feb 06 '21 08:02 icebox

Hi,

I am using Typescript and tried the solution from @icebox, but still get this error message: TypeError: Cannot read property 'addControl' of null.

I have the same versions as mentioned by @icebox

My code looks like this:

/** @jsxImportSource @emotion/react */
import 'next';
import Head from 'next/head';
import { useCallback, useRef, useState } from 'react';
import ReactMapGL from 'react-map-gl';
import Geocoder from 'react-map-gl-geocoder';

// Create the parameters for the routing request:

// const DynamicComponentWithNoSSR = dynamic(() => import('../components/Map'), {
//   ssr: false,
// });

// const dynamicComponent = () => <DynamicComponentWithNoSSR />;
// export default dynamicComponent;

type ViewportType = {
  width: string;
  height: string;
  latitude: number;
  longitude: number;
  zoom: number;
};

type HomeType = {
  mapboxToken: string;
};

export default function Home(props: HomeType) {
  const [viewport, setViewport] = useState({
    width: '100vw',
    height: '100vh',
    latitude: 48.8685,
    longitude: 2.328549,
    zoom: 15,
  });
  const mapRef = useRef();
  const handleViewportChange = useCallback(
    (newViewport) => setViewport(newViewport),
    [],
  );

  const handleGeocoderViewportChange = useCallback((newViewport) => {
    const geocoderDefaultOverrides = { transitionDuration: 1000 };

    return handleViewportChange({
      ...newViewport,
      ...geocoderDefaultOverrides,
    });
  }, []);

  return (
    <div>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
        <link
          href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css"
          rel="stylesheet"
        />
      </Head>

      <main>
        <ReactMapGL
          {...viewport}
          mapStyle="mapbox://styles/mapbox/streets-v9"
          mapboxApiAccessToken={props.mapboxToken}
          onViewportChange={handleViewportChange}
        >
          <Geocoder
            mapRef={mapRef}
            onViewportChange={handleGeocoderViewportChange}
            mapboxApiAccessToken={props.mapboxToken}
            position="top-left"
          />
        </ReactMapGL>
        {/* <Map viewport={viewport} setViewport={setViewport} /> */}
      </main>
    </div>
  );
}

export function getServerSideProps() {
  return { props: { mapboxToken: process.env.MAPBOX_API_TOKEN || null } };
}

Anyone having a solution for that?

Thanks a lot.

uebriges avatar Mar 10 '21 14:03 uebriges

Hey @uebriges, you need to pass mapRef as a ref to ReactMapGL. The geocoder uses that handle to access the Mapbox map instance from the React Map GL instance.

SamSamskies avatar Mar 10 '21 14:03 SamSamskies

Hi @SamSamskies,

Thanks a lot. It worked now also with the latest version of react-map-gl (6.1.10).

uebriges avatar Mar 10 '21 15:03 uebriges