slutske22 / react-esri-leaflet

react components for esri-leaflet
https://codesandbox.io/s/github/slutske22/react-esri-leaflet/tree/master/examples/ts
MIT License
37 stars 5 forks source link

Issue with refs + Typescript (TiledMapLayer) #15

Closed moranbw closed 2 years ago

moranbw commented 2 years ago

Perhaps related to this issue, I'm having some issues with refs andTiledMapLayer. Minimal example of my code is below:

import React from 'react';
import { MapContainer, TileLayer, ZoomControl } from 'react-leaflet'
import { TiledMapLayer } from 'react-esri-leaflet';
import { TiledMapLayer as EsriTiledMapLayer } from 'esri-leaflet';
import { LatLngBoundsExpression, LatLngTuple, Map as LeafletMap, TileLayer as LeafletTileLayer } from 'leaflet';
import bbox from '@turf/bbox';
import "./Map.css";
import { useTrackedState } from '../../state';

export default function Map() {
    const state = useTrackedState();
    const [map, setMap] = React.useState<LeafletMap>();
    const esriLayerRef= React.useRef<EsriTiledMapLayer>(null);

    const bboxArray = bbox(JSON.parse(state.features));
    const corner1: LatLngTuple = [bboxArray[1], bboxArray[0]];
    const corner2: LatLngTuple = [bboxArray[3], bboxArray[2]];
    const bounds: LatLngBoundsExpression = [corner1, corner2];

    /** if panel is collapsed, reset the map and tile layer **/
    React.useEffect(() => {
        let tileLayer = esriLayerRef.current;
        if (map && tileLayer) {
            map.invalidateSize();
            tileLayer.redraw();
        }
    }, [state.panelCollapsed]);

    return (
        <MapContainer bounds={bounds} id="projectMap" zoomControl={false} whenCreated={setMap}>
                <TiledMapLayer
                    ref={navLayerRef}
                    maxNativeZoom={10} url="https://server.arcgisonline.com/ArcGIS/rest/services/the/layer"
                />
            <ZoomControl position='topright' />
        </MapContainer>
    );

}

Perhaps my tsconfig is too strict...but I'm receiving the following error:

Type 'RefObject<TiledMapLayer>' is not assignable to type 'Ref<RefObject<TiledMapLayer>> | undefined'.
  Type 'RefObject<TiledMapLayer>' is not assignable to type 'RefObject<RefObject<TiledMapLayer>>'.
    Property 'current' is missing in type 'TiledMapLayer' but required in type 'RefObject<TiledMapLayer>'.ts(2322)
[index.d.ts(81, 18): ]()'current' is declared here.
[index.d.ts(133, 9): ]()The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & TiledMapLayerOptions & RefAttributes<RefObject<TiledMapLayer>>'

Is there something going on with the way forwardRef is being used? Let me know if there's any more information I can provide.

Thanks -- and great work on this project!

slutske22 commented 2 years ago

Thanks for opening the issue, and providing code. If you could create a codesandbox demonstrating the issue, it would be immensely helpful. I am extremely busy and have very little time to recreate issues, but if you can present me with the issue in a sandbox, I can take a look, thanks.

moranbw commented 2 years ago

@slutske22 thanks for the prompt reply. Here's a minimal example: https://stackblitz.com/edit/vitejs-vite-vrfcaw?file=src/App.tsx

You should be able to see the TypeScript issue on line 18. In my own code, I'm just currently doing a //@ts-ignore to supress the issue.

Thanks in advance.

(note this code editor only seems to work well in Chrome, not Firefox)

slutske22 commented 2 years ago

I see the issue. I think I know what the problem is - I've wrapped the return value of the ref in forwardRef in React.RefObject, which I guess is wrong. I'll try to come back and fix this when I have time. For now you can fake it out by doing this

const tileLayerRef = React.useRef<React.RefObject<EsriTiledMapLayer>>(null);

// then to still get intellisense when using it:
(tileLayerRef.current as EsriTiledMapLayer).bringToBack() // or some other leaflet layer method here

Not sure when I can push a new version with the fix, I'll leave this open for now.

moranbw commented 2 years ago

@slutske22 thanks for the workaround. No rush as it's not blocking me. If I have any time I may look into it as well, if you're open to contributions.

slutske22 commented 2 years ago

This is fixed in version 2, which is currently in a @next version. You can try it out here: https://www.npmjs.com/package/react-esri-leaflet/v/2.0.0, npm i react-esri-leaflet@next, Will publish as official version soon.