# Clusters ghost after updating tileLayer in Leaflet map

**URL:** https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331
**Category:** Help
**Created:** [October 17, 2018, 7:00pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331 "2018-10-17T19:00:37Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 17, 2018, 7:00pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/1 "2018-10-17T19:00:37Z")

</div>

When I update the main map tiling layer, and then zoom in and out of the map, the clusters layer seems to ghost whereas it should clear and re-render different clusters on each zoom level.

It’s easy to repro here, just change the default styling and then zoom and and out of the map:

> **[Montreal 311 incidents in 2016-2018](https://beta.observablehq.com/@john-clarke/montreal-311-incidents-in-2016-2018#map_styling)**
>
> An Observable notebook by John Clarke.

---

<div class="post-metadata">

### Author: ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)
#### Post date: [October 17, 2018, 8:22pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/2 "2018-10-17T20:22:41Z")

</div>

Try caching your layers on the `map` object rather than the `global` object so that you automatically discard them when the `map` is re-initialized.

Here’s a diff\* using our new compare view:

> **[Observable](https://beta.observablehq.com/compare/90d53eabffb449cc...e8a559026611c239)**
>
> A better way to code.

\*The fork won’t render correctly because of the CORS restrictions on your data, but the code at least is still readable.

---

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 17, 2018, 11:41pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/3 "2018-10-17T23:41:15Z")

</div>

@mbostock Thanks. I forked your example (nice diff view, by the way!) and the issue seems to persist.

I’ll to try to fix the CORS issue, for some reason it seemed like I need to `Header always set Access-Control-Allow-Credentials "true"` so that I could enable `force-cache` in my d3.csv calls. And that then prevents a wildcard for `Access-Control-Allow-Origin`. Perhaps there is a free server I could use instead to serve the csv – it was too big for `gist`.

---

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 18, 2018, 12:39am UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/4 "2018-10-18T00:39:31Z")

</div>

@mbostock I’ve fixed the CORS problem by uploading to gist (It just barely worked this time due to some improvements I made to the filesize). And I made the changes you suggested.

[https://beta.observablehq.com/@john-clarke/montreal-311-incidents-in-2016-2018](https://beta.observablehq.com/@john-clarke/montreal-311-incidents-in-2016-2018) – so you should be able to fork again and reproduce.

Just for reference this is what happens – if you zoom in and out a few times:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/8/85f67bc76b10903f97b88f94fff5494b9cd64d7c.jpeg)

---

<div class="post-metadata">

### Author: ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)
#### Post date: [October 18, 2018, 12:41am UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/5 "2018-10-18T00:41:25Z")

</div>

I’m not seeing the suggested changes applied—the published notebook still uses `global`?

---

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 18, 2018, 1:44am UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/6 "2018-10-18T01:44:33Z")

</div>

Weird. It is as if the publish isn’t working. I’ve forked and shared to  
[https://beta.observablehq.com/d/7f921a18818167d0](https://beta.observablehq.com/d/7f921a18818167d0) (with the changes you suggested)

---

<div class="post-metadata">

### Author: ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)
#### Post date: [October 18, 2018, 7:00pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/7 "2018-10-18T19:00:01Z")

</div>

Here’s how I’d approach this problem. ([Compare.](https://beta.observablehq.com/compare/90d53eabffb449cc...4157ac008e7d4a78))

> **[Montreal 311 incidents in 2016-2018 / Observable](https://beta.observablehq.com/d/4157ac008e7d4a78)**
>
> A better way to code.

To summarize:

- In the `map` cell, create the three layers (osm, marker, heatmap) for the map immediately, but leave the marker and heatmap layers empty. Register _zoomstart_ and _zoomend_ listeners to toggle the presence of the heatmap layer as desired based on zoom level.

- In a separate “side-effect” cell that references both `map` and `filtered_incidents`, populate the contents of the marker and heatmap layers, replacing whatever was there before, and then fly to the desired bounds.

Or in other words, try to **minimize side-effects across cells**. We want to use side-effects here so that we can replace the map layers without re-initializing the map completely, but everything else can be safely moved to the `map` cell to simplify the logic and avoid bugs.

---

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 18, 2018, 10:03pm UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/8 "2018-10-18T22:03:51Z")

</div>

Wow, that looks so much cleaner – and seems to have fixed the original issue. Thanks for looking into it.

What would you recommend to be best way to publish this? I could just copy it over to the original notebook, or publish the fork and hide the original notebook?

BTW, I really like the diff – views – so nice.

---

<div class="post-metadata">

### Author: ![john-clarke](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/john-clarke/32/219_2.png) [@john-clarke](https://talk.observablehq.com/u/john-clarke)
#### Post date: [October 19, 2018, 12:03am UTC](https://talk.observablehq.com/t/clusters-ghost-after-updating-tilelayer-in-leaflet-map/1331/9 "2018-10-19T00:03:35Z")

</div>

I ended up forking, then publishing again – that works well (with a version number 2)

> **[Montreal 311 incidents in 2016-2018](https://beta.observablehq.com/@john-clarke/montreal-311-incidents-in-2016-2018/2)**
>
> An Observable notebook by John Clarke.

@mbostock – thanks again.
