@lad-sapienza/scms-core 0.1.0-alpha.4 → 0.1.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -326,12 +326,13 @@ export class LayerControlClass implements IControl {
326
326
 
327
327
  if (hasChanged) {
328
328
  this.props = newProps;
329
- // Use requestAnimationFrame to ensure the update happens after current execution
330
- requestAnimationFrame(() => {
331
- if (this.root && this.isAddedToMap) {
332
- this.root.render(<LayerControlUI {...this.props} />);
333
- }
334
- });
329
+ // Render immediately — this is already called from a useEffect (well
330
+ // after React's render phase), so there's no synchronous-update
331
+ // hazard to defer for. Deferring via requestAnimationFrame instead
332
+ // left a window where the DOM (e.g. a basemap radio's checked state)
333
+ // visibly lagged behind the already-updated React state, sometimes
334
+ // indefinitely if the tab wasn't actively painting frames.
335
+ this.root.render(<LayerControlUI {...this.props} />);
335
336
  }
336
337
  }
337
338
  }
@@ -1,4 +1,4 @@
1
- import { useState, useMemo, useEffect, useRef } from 'react';
1
+ import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
2
2
  import MapLibreMap, {
3
3
  NavigationControl,
4
4
  FullscreenControl,
@@ -310,20 +310,34 @@ export function Map({
310
310
  }, [allVectorLayers]);
311
311
 
312
312
  // Handle vector layer visibility toggle
313
- const handleVectorLayerToggle = (layerId: string) => {
313
+ //
314
+ // Wrapped in useCallback (both here and below) so its identity stays
315
+ // stable across renders — it's one of two functions passed into the
316
+ // "add LayerControl as an IControl" effect's dependency array. Left as a
317
+ // plain function, it got a new reference on *every* render (including
318
+ // the one triggered by clicking a basemap radio, since that sets
319
+ // activeBaseLayer state on this very component), which spuriously
320
+ // refired that effect on every click. Each refire tore down the old
321
+ // IControl and created a fresh one — and since the cleanup removed
322
+ // whatever layerControlRef.current happened to point to *at cleanup
323
+ // time* rather than the specific instance being torn down, the freshly
324
+ // created (correct) control was the one actually getting removed a tick
325
+ // later, leaving the stale first control (still showing the original
326
+ // basemap selected) as the only one left on the map.
327
+ const handleVectorLayerToggle = useCallback((layerId: string) => {
314
328
  setVectorLayerVisibility(prev => ({
315
329
  ...prev,
316
330
  [layerId]: !prev[layerId]
317
331
  }));
318
- };
332
+ }, []);
319
333
 
320
- // Handle search for vector layers
321
- const handleLayerSearch = (layerId: string, query: SearchQuery) => {
334
+ // Handle search for vector layers — see handleVectorLayerToggle above.
335
+ const handleLayerSearch = useCallback((layerId: string, query: SearchQuery) => {
322
336
  setLayerSearchQueries(prev => ({
323
337
  ...prev,
324
338
  [layerId]: query
325
339
  }));
326
- };
340
+ }, []);
327
341
 
328
342
  // Load data for all vector layers
329
343
  useEffect(() => {
@@ -467,13 +481,14 @@ export function Map({
467
481
  map.addControl(control, position);
468
482
 
469
483
  return () => {
470
- if (layerControlRef.current && map) {
471
- setTimeout(() => {
472
- if (layerControlRef.current && map) {
473
- map.removeControl(layerControlRef.current);
474
- }
475
- }, 0);
476
- }
484
+ // Remove this specific control instance, not whatever
485
+ // layerControlRef.current happens to point to when the timeout
486
+ // fires — if this effect ever refires before the timeout runs, the
487
+ // ref will already point at the *new* control, and reading it here
488
+ // would remove that one instead of this (correct) cleanup target.
489
+ setTimeout(() => {
490
+ map.removeControl(control);
491
+ }, 0);
477
492
  };
478
493
  }, [mapLoaded, layerControl, resolvedBaseLayers, allVectorLayers.length, handleLayerSearch]);
479
494
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lad-sapienza/scms-core",
3
- "version": "0.1.0-alpha.4",
3
+ "version": "0.1.0-alpha.6",
4
4
  "description": "Framework components and Astro integrations for s:CMS — DataTb, Gallery, Map, ZoteroGeoViewer, Record.",
5
5
  "type": "module",
6
6
  "license": "BSD-0-Clause",