Map: incident pins rebuilt every second (clock re-render) — pin pulse restarts before it completes #279

Closed
opened 2026-10-05 03:52:40 -04:00 by logan · 0 comments
Owner

Problem

LiveView re-renders every second (the wall-bar clock, setClock in components/LiveView.tsx), and MapView is not memoised, so FanIncidentLayer rebuilds every incident marker's L.divIcon inline on each render (components/MapView.tsx ~1076-1078). react-leaflet calls setIcon when the icon prop identity changes, and DivIcon rewrites innerHTML, so every incident pin's DOM is replaced once a second.

Visible effect since #238 (PR #276) passes pulseIncidentIds: the .node-pulse-ring animation (app/globals.css, 1.8s) restarts every 1s, so the pulse never completes a cycle and looks like a stutter, not a pulse. It also costs a full marker DOM rewrite per second on an all-day wall.

Fix direction

Memoise the incident (and fan) icons per (type, severity, precision, pulse, members) key, or wrap MapView / FanIncidentLayer in React.memo so the clock tick doesn't reach the markers. MapView-owned; not done in #276 because 237-map owns MapView this batch.

Acceptance

  • A pulsing pin completes its 1.8s ring animation (verify in a browser).
  • Clock ticks don't call setIcon on unchanged incident markers.

Found reviewing PR #276 (server-26#238).

## Problem `LiveView` re-renders every second (the wall-bar clock, `setClock` in `components/LiveView.tsx`), and `MapView` is not memoised, so `FanIncidentLayer` rebuilds every incident marker's `L.divIcon` inline on each render (`components/MapView.tsx` ~1076-1078). react-leaflet calls `setIcon` when the icon prop identity changes, and DivIcon rewrites `innerHTML`, so every incident pin's DOM is replaced once a second. Visible effect since #238 (PR #276) passes `pulseIncidentIds`: the `.node-pulse-ring` animation (`app/globals.css`, 1.8s) restarts every 1s, so the pulse never completes a cycle and looks like a stutter, not a pulse. It also costs a full marker DOM rewrite per second on an all-day wall. ## Fix direction Memoise the incident (and fan) icons per (type, severity, precision, pulse, members) key, or wrap `MapView` / `FanIncidentLayer` in `React.memo` so the clock tick doesn't reach the markers. MapView-owned; not done in #276 because 237-map owns MapView this batch. ## Acceptance - A pulsing pin completes its 1.8s ring animation (verify in a browser). - Clock ticks don't call `setIcon` on unchanged incident markers. Found reviewing PR #276 (server-26#238).
logan added the
type
bug
area/maparea/frontend
priority
p2
kind
behavior-bug
labels 2026-10-05 03:52:40 -04:00
logan closed this issue 2026-10-05 04:02:33 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/server-26#279