I use React-leaflet to produce maps on my ReactJS app. The maps works perfectly when I use a .json file with the data in a GeoJSON format.
Now I have to use a data from our own API. I call the API and the datas are properly return by it. But there is my problem :
When I don't put the data in my component, the console.log of the state return {} (the initaialization) and then it reload automatically and the return the datas I need. But when I put the data in my component I've got an error and the state doesn't update at all.
The code with the API :
import React, {useEffect} from 'react';
import {useLocation} from 'react-router-dom'
import Graph3Vagues from './Graphiques/Troisvagues'
import CarteRisquesREGCour from './Cartes/Cartes_risques_rendement/cartes_risques_REG_cour'
import LegendeCarteRiskRDT from './Cartes/legendes_risques_rendement';
function RisquesRdt() {
const { state } = useLocation();
const { idExploit } = state;
const [dataReg, setDataReg] = React.useState({})
const [Risques7, setR7] = React.useState(0)
const [Risques20, setR20] = React.useState(0)
const [Risques50, setR50] = React.useState(0)
const [dataPerso, setDP]= React.useState();
const [dataVagues7, setDV7]= React.useState();
const [dataVagues20, setDV20]= React.useState();
const [dataVagues50, setDV50]= React.useState();
const [maximum, setmax]= React.useState();
const [dataQ1, setDQ1]= React.useState();
const [dataQ2, setDQ2]= React.useState();
const [dataQ3, setDQ3]= React.useState();
const [Taille, setTaille]= React.useState();
useEffect ( () => {
fetch('API URL' + idExploit)
.then( (response) => {
return response.json()
})
.then(response =>{
setR7(response.risques7)
setR7(prev => {
return prev;
})
setR20(response.risques20)
setR20(prev => {
return prev;
})
setR50(response.risques50)
setR50(prev => {
return prev;
})
})
fetch('API URL' + idExploit)
.then( (response) => {
return response.json()
})
.then(response =>{
setDP(prev => {
return prev;
})
setDV7(response.dataVagues7)
setDV7(prev => {
return prev;
})
setDV20(response.dataVagues20)
setDV20(prev => {
return prev;
})
setDV50(response.dataVagues50)
setDV50(prev => {
setmax(prev[prev.length-1].y+20)
setDQ1([{x:prev.length/4, y:0}, {x:prev.length/4, y:80}])
setDQ2([{x:prev.length/2, y:0}, {x:prev.length/2, y:80}])
setDQ3([{x:prev.length*3/4, y:0}, {x:prev.length*3/4, y:80}])
setTaille(prev.length)
return prev;
})
})
fetch('API URL' + idExploit)
.then( (response) => {
return response.json()
})
.then(response =>{
let idPRA
let idReg
idPRA = response.idPetiteRegionAgricole
idReg = response.idRegion
fetch('API URL' + idReg)
.then( (response) => {
return response.json()
})
.then(response =>{
setDataReg(response.data)
setDataReg(prev => {
return prev;
})
})
})
}, [idExploit])
return (
<div >
<Entete titre="Risques rendement"/>
<div className='container'>
<div className='titre'>Quel est mon niveau de risques ? </div>
<div className='titre'>{console.log(dataReg)} </div>
<div className='paragraphe'>Une comparaison aux {Taille} exploitations spécialisées en grandes cultures, représentatives des régions agricoles françaises. Résultats sont représentés en % de pertes par rapport au produit brut.</div>
<div className='paragraphe'> Votre exploitation est représentée par un trait noir </div>
<div className='dispLigne'>
<div className='dispLeftOpt'>
<div style={{marginTop:'10px'}}>
<Graph3Vagues dataPerso={dataPerso} dataVagues7={dataVagues7} dataVagues20={dataVagues20} dataVagues50={dataVagues50} maximum={maximum} dataQ1={dataQ1} dataQ2={dataQ2} dataQ3={dataQ3} />
</div>
<div className='row axeX'>
<div className='textX' >25% les moins exposées </div>
<div className='textX'>50%</div>
<div className='textX'>25% les plus exposées</div>
</div>
</div>
</div>
{(TypeRisque==='Courant' && Echelle==='REG') ? (<CarteRisquesREGCour data={dataReg}/>)}
</div>
<OADMenu idExploit={idExploit}/>
</div>
);
}
export default RisquesRdt;
The code of the map :
import React from 'react';
import { MapContainer, TileLayer, GeoJSON } from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
function CarteRisquesREGCour({data}) {
const bbox = require('geojson-bbox');
const extent = bbox(data);
function getColor(d) {
return d > 3500 ? '#530d0d' :
d > 2750 ? '#530d0d' :
d > 2500 ? '#69120e' :
d > 2000 ? '#7f1810' :
d > 1750 ? '#941d11' :
d > 1500 ? '#aa2213' :
d > 1000 ? '#c02714' :
d > 750 ? '#cb3915' :
d > 670 ? '#cf5315' :
d > 650 ? '#d36e15' :
d > 600 ? '#d78815' :
d > 520 ? '#dba215' :
d > 490 ? '#debd15' :
d > 465 ? '#e2d715' :
d > 430 ? '#d6d616' :
d > 400 ? '#c7ce17' :
d > 360 ? '#b7c517' :
d > 320 ? '#a8bd18' :
d > 275 ? '#98b519' :
d > 210 ? '#89ad1a' :
d > 190 ? '#6f9917' :
d > 165 ? '#558415' :
d > 140 ? '#3b6f12' :
d > 110 ? '#205a10' :
d > 0 ? '#06450e' :
'#ffffff'; //le dernier on ne met pas son nom car le reste
}
function style(feature) {
return {
fillColor: getColor(feature.properties.risques7),
weight: 0.5,
opacity: 1,
color: '#000000',
dashArray: '3',
fillOpacity: 0.7,
};
}
const [selected, setSelected] = React.useState({});
function highlightFeature(e) {
var layer = e.target;
const { risques7, libelle} = e.target.feature.properties;
setSelected({
risques:risques7,
libelle:libelle,
});
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
}
function resetHighlight(e) {
setSelected({});
e.target.setStyle(style(e.target.feature));
}
function onEachFeature(feature, layer) {
layer.on({
click: highlightFeature,
mouseout: resetHighlight
});
}
return (
<div className="totalCarte">
<div className="">
{!selected.risques && (
<div className='paragraphe infos_carte'>
Cliquez sur une zone pour avoir plus de détails
</div>
)}
{selected.risques && (
<div className='paragraphe infos_carte' >
{selected.libelle} : {selected.risques} €/ha
</div>
)}
<MapContainer
zoom={10}
scrollWheelZoom={false}
maxZoom={14}
center={[48.832,2.623]}
whenReady={e => {
e.target.flyToBounds([
[extent[1],extent[0]],
[extent[3], extent[2]]
]);
}}
>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{data && (
<GeoJSON data={data}
style={style}
onEachFeature={onEachFeature} />
)}
</MapContainer>
</div>
</div>
);
}
export default CarteRisquesREGCour;
What I don't understand is that the chart "Graph3Vagues" is waiting to have the date from it's API but not the map.
I tried
Can someone help me please ?
Thanks to an adapatation of the validating answer of [this question][1], I solved my probleme, by adding a loading state.
I add in the code with the API :
function RisquesRdt() {
const { state } = useLocation();
const { idExploit } = state;
const [loading, setLoading] = React.useState(true);
...
useEffect ( () => {
...
.then(response =>{
setDataReg(response.data)
setDataReg(prev => {
setLoading(false);
return prev;
})
})
})
}, [idExploit])
...
{(TypeRisque==='Courant' && Echelle==='REG') ? (<CarteRisquesREGCour data={dataReg} loading={loading}/>)}
</div>
<OADMenu idExploit={idExploit}/>
</div>
);
}
export default RisquesRdt;
And in the map file :
import React from 'react';
import { MapContainer, TileLayer, GeoJSON } from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
function CarteRisquesREGCour({data, loading}) {
const bbox = require('geojson-bbox');
const extent = bbox(data);
...
return (
<div className="totalCarte">
{!loading && (
<div className="">
...
{data && !loading && (
<GeoJSON data={data}
style={style}
onEachFeature={onEachFeature} />
)}
</MapContainer>
</div>
)}
</div>
);
}
export default CarteRisquesREGCour;
```
And with everything run works like a charm (except the highlight)
[1]: https://stackoverflow.com/questions/73432932/api-is-not-working-inside-oneachfeature-react-leaflet-function