Mapbox-gl-js: map.addLayer() mutates the input layer's source

Created on 27 Jul 2017  路  9Comments  路  Source: mapbox/mapbox-gl-js

I've got a really weird bug that I have finally been able to reproduce. I attempt to create a polyline from some GeoJSON data structure. The GeoJSON structure has a source property that contains the longitude and latitude coordinates.

When I examine the GeoJSON object in the JavaScript console in the Chrome Dev Tools, initially it shows the source property as an Object as it should. But when you expand the GeoJSON object it then shows the source property value as a string and it changes it to the same value as the id of the GeoJSON object. So obviously since the source property is a string it no longer works as a valid GeoJSON object for my polyline.

Really really weird. I cannot figure this out. Check out the following screenshot:

screen shot 2017-07-27 at 2 09 51 pm

See? It shows source as an Object. But when you expand it, its a string AND it matches the id of the object every time.

If you look at the following JSFiddle:

https://jsfiddle.net/mwfrcroj/

You can see that the GeoJSON data structure is setup properly. Clearly, the source property is not a string. It has the correct object structure. But something weird happens when the layer is added to the map. The source is changed to a string as you can see in the console.

ADDITIONALLY, if you comment out the map.addLayer() command:

// map.addLayer(solidRoute)

And run the fiddle again, you will see that the source does NOT change to a string. So the center of this problem is originating when the layer is added to the map via MapBox.

mapbox-gl-js version: 0.39.1

Steps to Trigger Behavior

  1. Use this fiddle: https://jsfiddle.net/mwfrcroj/
  2. Run the fiddle
  3. Examine the JavaScript console
  4. Note that the source property of the GeoJSON object gets changed from it's object to a string

Expected Behavior

The source property should continue to be an Object and should not change.

Actual Behavior

The source property gets changed to a string with the same value as the id of the GeoJSON object. Therefore the GeoJSON object will no longer work since there are no longer coordinates.

bug

Most helpful comment

/facepalm

Okay so the code is working fine and I guess the mutation is just a side effect. Thank you for your help!

All 9 comments

Turns out that adding layer-specific sources also mutates the input layer object's source parameter. Under the hood, layer-specific sources invoke the traditional map.addSource() workflow.

@Jakobud I suggest keeping your geojson object in a separate variable and just pass it in by reference.

Interesting. Can you elaborate on this? Because I'm simply following the documentation example on how to draw a polyline: https://www.mapbox.com/mapbox-gl-js/example/geojson-line/

Are you saying this isn't the proper way to do it?

@Jakobud nah, you're doing it right. It's just that if you want to keep your geojson around for later use, you'll want to store it separately from the layer object, because .addLayer() will mutate the layer object you feed it.

EDIT: turns out that this IS a bug, though the above would serve as a viable workaround

This is a bug -- Map#addLayer shouldn't ever mutate the input.

I'm not trying to keep it around for later. The MapBox simply isn't adding my polyline layer to the map. I don't get any JS errors about invalid GeoJSON structure either. That is why I was trying to console.log my input, just to make sure it was correct.

Is there anything about my syntax that is incorrect? How come the documentation example works fine but mine brings up this bug? I'm not immediately seeing the difference.

@Jakobud ah, geojson uses longitude-latitude order. Your linestring is currently near a pole:

screen shot 2017-07-27 at 4 02 15 pm

/facepalm

Okay so the code is working fine and I guess the mutation is just a side effect. Thank you for your help!

Turns out we have an issue for the input mutation: #4040.

I just came across this myself. If I want to draw a rectangle by updating the source coordinates as the mouse is dragged, Adding a separate source object to the map and then using .setData on that object does the trick (with a separate geojson variable).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aaronlidman picture aaronlidman  路  3Comments

foundryspatial-duncan picture foundryspatial-duncan  路  3Comments

iamdenny picture iamdenny  路  3Comments

Scarysize picture Scarysize  路  3Comments

samanpwbb picture samanpwbb  路  3Comments