fix: monter la carte une seule fois après chargement du style
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 ── */
|
/* ── Logo ── */
|
||||||
.smap-logo {
|
.smap-logo {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep,
|
|||||||
const [spotScores, setSpotScores] = useState({});
|
const [spotScores, setSpotScores] = useState({});
|
||||||
const [viewState, setViewState] = useState(INITIAL_VIEW);
|
const [viewState, setViewState] = useState(INITIAL_VIEW);
|
||||||
const [layerOpacity, setLayerOpacity] = useState(1);
|
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 [dataDate, setDataDate] = useState(null);
|
||||||
|
|
||||||
const tilesOrigin = window.location.origin;
|
const tilesOrigin = window.location.origin;
|
||||||
@@ -170,12 +170,17 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep,
|
|||||||
.catch(() => {});
|
.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(() => {
|
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(r => r.json())
|
||||||
.then(style => setMapStyle(cartoonizeStyle(style)))
|
.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
|
// Load coastal spots once
|
||||||
@@ -221,6 +226,10 @@ export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep,
|
|||||||
const OBS_STYLES = makeLayerStyles(false, layerOpacity);
|
const OBS_STYLES = makeLayerStyles(false, layerOpacity);
|
||||||
const FORE_STYLES = makeLayerStyles(true, layerOpacity);
|
const FORE_STYLES = makeLayerStyles(true, layerOpacity);
|
||||||
|
|
||||||
|
if (!mapStyle) {
|
||||||
|
return <div className="smap-placeholder" />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Map
|
<Map
|
||||||
ref={mapRef}
|
ref={mapRef}
|
||||||
|
|||||||
Reference in New Issue
Block a user