Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VectorTileLayer not working with vite project #22

Open
shaiRos opened this issue Jun 10, 2024 · 4 comments
Open

VectorTileLayer not working with vite project #22

shaiRos opened this issue Jun 10, 2024 · 4 comments

Comments

@shaiRos
Copy link

shaiRos commented Jun 10, 2024

I have an app created with vite. Installed this library and I'm trying to use a vector tile to display in the map. I have tried the url used for the example for this library and even from the esri documentation here for vector tiles. Even created another repo where it's just the base template that vite installs (react-javascript)

image

and it's giving me this main error
Uncaught TypeError: Cannot use 'in' operator to search for '_leaflet_id' in undefined

Things I tried:

  • esri-leaflet-vector is installed (VectorBasemapLayer works perfectly, VectorTileLayer doesn't)
  • create vite base app with just this library installed
  • copied the dependencies versions used in the example (except react (v18.3.1 used) and react-dom (v18.3.1 used))
  • tried vectortileserver url links from esri documention for vector tiles

help would be apprecitated.

@slutske22
Copy link
Owner

Thank you for reporting this issue (and doing a well-written writeup).

I am able to reproduce this by spinning up an npm create vite reproduce-example-project with react and typescript, installing everything, and trying to use VectorTileLayer.

This is extremely odd. I have no had this issue when using parcel or webpack. Let me do some digging and see if I can come up with anything as to why using this library with vite creates this issue.

Have you tried using the "vanilla" version of a VectorTileLayer with Vite? Does that work? If that causes the same problem, it helps debug whether the issue in is this wrapper library, or upstream somewhere.

@slutske22
Copy link
Owner

sigh so this problem is very strange indeed. Looking into it, the author of leaflet answered another person with the same here: Cannot read property '_leaflet_id' of undefined:

This happens when tilelayer variable is undefined at the moment when this line executes. Put a debugger statement there and figure it out, shouldn't be hard.

Digging into the leaflet src code, when the map.removeLayer event fires, if the layer that is being removed doesn't exist, this will happen because of this:

https://github.com/Leaflet/Leaflet/blob/eee1a4aeddd8f7bf6172ea902e32aab97770a470/src/layer/Layer.js#L179

Screenshot 2024-06-10 at 10 55 20 AM

IMO this is a small area where the leaflet src code could probably be improved. I don't personally understand why removeLayer is firing at all, or why its firing with an undefined layer in this particular use case. However, a workaround for now is to do this: in your code, anywhere after importing leaflet, but before using a VectorTileLayer, add this:

  L.Map.include({
    removeLayer(layer: L.Layer) {
      if (!layer) return this;

      const id = L.Util.stamp(layer);

      if (!this._layers[id]) {
        return this;
      }

      if (this._loaded) {
        layer.onRemove(this);
      }

      delete this._layers[id];

      if (this._loaded) {
        this.fire("layerremove", { layer });
        layer.fire("remove");
      }

      // @ts-expect-error leaflet TS very incomplete
      layer._map = layer._mapToAdd = null;

      return this;
    },
  });

This will overwrite the Map.removeLayer method to not call stamp on smething that is undefined, thereby avoiding the code that would throw an error.

This is a hacky workaround, but it does work. I am trying to brainstorm why leaflet code would ever get to running Map.removeLayer on something that is undefined, in this case only. There is something under the hood of react-leaflet with createLayerComponent that may be causing this, but I'm not sure what.

If you are familiar with these things, I'm open to suggestion on what could be going wrong or how to fix it, but for now, at least you have a monkeypatch solution.

@slutske22
Copy link
Owner

Another thought

React 18 renders everything twice when using React.StrictMode, which is a default part of a vite project (ew). While it can actually help debug problems, in this case, I think the issue is that react is mounting and unmounting the VectorTileLayer too quickly, and the underlying leaflet layer is not being created in time.

Completely separately from the other solution I posted, removing StrictMode solves the problem for me as well. Perhaps this is not a vite issue, but rather a react-esri-leaflet issue when using strictmode in react 18.

@shaiRos
Copy link
Author

shaiRos commented Jun 10, 2024

Thanks! removing the strictmode worked (and the previous solution too). I did notice when i ran the preview of (npm run build) by vite, the app ran without errors with the VectorTile line in the code, but the layer was still not added to the map. And running on build preview removes that behavior relating to strict mode...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants