From 79f834e1f05c8a44cd6c743984e95e1f0bb124ff Mon Sep 17 00:00:00 2001 From: Gwadaking Date: Tue, 14 Apr 2026 02:48:08 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20monter=20la=20carte=20une=20seule=20fois?= =?UTF-8?q?=20apr=C3=A8s=20chargement=20du=20style?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le style basculait de positron (URL) vers cartoonizeStyle() ~500 ms après le premier rendu. Ce setStyle() déclenchait une réinscription des sources/layers (react-map-gl v8 / maplibre-gl v5) qui échouait silencieusement — les bancs de sargasses devenaient invisibles. La carte est désormais montée UNE SEULE FOIS quand le style est prêt (avec timeout 4 s → fallback positron). Plus de transition post-mount, plus de race condition. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/Map/SargassesMap.css | 7 +++++++ frontend/src/components/Map/SargassesMap.jsx | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Map/SargassesMap.css b/frontend/src/components/Map/SargassesMap.css index 258f246..92049f8 100644 --- a/frontend/src/components/Map/SargassesMap.css +++ b/frontend/src/components/Map/SargassesMap.css @@ -1,3 +1,10 @@ +/* ── Placeholder avant chargement du style ── */ +.smap-placeholder { + width: 100%; + height: 100vh; + background: #3ab5e6; /* couleur océan = pas de flash blanc */ +} + /* ── Logo ── */ .smap-logo { position: absolute; diff --git a/frontend/src/components/Map/SargassesMap.jsx b/frontend/src/components/Map/SargassesMap.jsx index 4593c92..03ad255 100644 --- a/frontend/src/components/Map/SargassesMap.jsx +++ b/frontend/src/components/Map/SargassesMap.jsx @@ -154,7 +154,7 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep, const [spotScores, setSpotScores] = useState({}); const [viewState, setViewState] = useState(INITIAL_VIEW); const [layerOpacity, setLayerOpacity] = useState(1); - const [mapStyle, setMapStyle] = useState(FALLBACK_STYLE); + const [mapStyle, setMapStyle] = useState(null); // null = style not yet ready const [dataDate, setDataDate] = useState(null); const tilesOrigin = window.location.origin; @@ -170,12 +170,17 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep, .catch(() => {}); }, []); - // Load cartoon map style + // Load cartoon map style once — map is only mounted when style is ready, + // preventing the setStyle() race condition that silently drops custom sources. useEffect(() => { - fetch('https://tiles.openfreemap.org/styles/bright') + const ctrl = new AbortController(); + const timeout = setTimeout(() => ctrl.abort(), 4000); // 4 s timeout + fetch('https://tiles.openfreemap.org/styles/bright', { signal: ctrl.signal }) .then(r => r.json()) .then(style => setMapStyle(cartoonizeStyle(style))) - .catch(() => {}); // keep positron on error + .catch(() => setMapStyle(FALLBACK_STYLE)) // positron fallback on error/timeout + .finally(() => clearTimeout(timeout)); + return () => ctrl.abort(); }, []); // Load coastal spots once @@ -221,6 +226,10 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep, const OBS_STYLES = makeLayerStyles(false, layerOpacity); const FORE_STYLES = makeLayerStyles(true, layerOpacity); + if (!mapStyle) { + return
; + } + return (