Reputation: 13
I tried to do it in this way.
I want to return multiple <LocationMarker>
for each "ev". But it's only returning one <LocationMarker>
for each "ev". for loop inside the storm variable is only executing once.
I also tried keeping for loop inside the return function but got an error.
Thanks in Advance
import { useState } from 'react';
import GoogleMapReact from 'google-map-react';
import LocationMarker from './LocationMarker';
import LocationInfoBox from './LocationInfoBox';
const NATURAL_EVENT_SEVERESTORMS = 'severeStorms';
const Map = ({ eventData, center, zoom }) => {
const [locationInfo, setLocationInfo] = useState(null);
const storms = eventData.map((ev) => {
if (ev.categories[0].id === NATURAL_EVENT_SEVERESTORMS) {
for (let i = 0; i < ev.geometry.length; i++) {
return (
<LocationMarker
lat={ev.geometry[i].coordinates[1]}
lng={ev.geometry[i].coordinates[0]}
type='severeStorms'
onClick={() => setLocationInfo({ id: ev.id, title: ev.title })}
/>
);
}
}
return null;
});
return (
<div className='map'>
<GoogleMapReact
bootstrapURLKeys={{ }}
defaultCenter={center}
defaultZoom={zoom}
>
{storms}
</GoogleMapReact>
{locationInfo && <LocationInfoBox info={locationInfo} />}
</div>
);
};
Map.defaultProps = {
center: {
lat: 42.3265,
lng: -122.8756,
},
zoom: 4,
};
export default Map;
Upvotes: 1
Views: 1929
Reputation: 53
You will have to add all LocationMarker in an array, and then return the array,
What you are doing now, is traversing the loop, and then on first index (i=0), returning the
<LocationMarker
lat={ev.geometry[i].coordinates[1]}
lng={ev.geometry[i].coordinates[0]}
type='severeStorms'
onClick={() => setLocationInfo({ id: ev.id, title: ev.title })}
/>
from storms function.
Upvotes: 0
Reputation: 6299
You have two nested loops there, so in order to get the actual array you need to concatenate each loop record, or just use reduce. Something like this should work:
import { useState } from 'react';
import GoogleMapReact from 'google-map-react';
import LocationMarker from './LocationMarker';
import LocationInfoBox from './LocationInfoBox';
const NATURAL_EVENT_SEVERESTORMS = 'severeStorms';
const Map = ({ eventData, center, zoom }) => {
const [locationInfo, setLocationInfo] = useState(null);
const storms = eventData.reduce((acc, ev, indx) => {
const geometries = ev.geometry.map((geo, geoIndx) => (
<LocationMarker
key={`${indx}-${geoIndx}`}
lat={geo.coordinates[1]}
lng={geo.coordinates[0]}
type='severeStorms'
onClick={() => setLocationInfo({ id: ev.id, title: ev.title })}
/>
)
// Concatenate previously collected records with this iteration map output
acc = acc.concat(geometries)
return acc
}, [])
return (
<div className='map'>
<GoogleMapReact
bootstrapURLKeys={{ }}
defaultCenter={center}
defaultZoom={zoom}
>
{storms}
</GoogleMapReact>
{locationInfo && <LocationInfoBox info={locationInfo} />}
</div>
);
};
Map.defaultProps = {
center: {
lat: 42.3265,
lng: -122.8756,
},
zoom: 4,
};
export default Map;
Upvotes: 0
Reputation: 796
You are returning the LocationMarker
JSX in the first iteration of the for
loop. Instead of it, you should use the map
method again.
const storms = eventData.map((ev) => {
if (ev.categories[0].id === NATURAL_EVENT_SEVERESTORMS) {
return ev.geometry.map((geo) => {
return (
<LocationMarker
lat={geo.coordinates[1]}
lng={geo.coordinates[0]}
type='severeStorms'
onClick={() => setLocationInfo({ id: ev.id, title: ev.title })}
/>
);
});
}
return null;
});
Also note that you have to add a 'key' property when iterating to render JSX list.
const storms = eventData.map((ev) => {
if (ev.categories[0].id === NATURAL_EVENT_SEVERESTORMS) {
return ev.geometry.map((geo) => {
return (
<LocationMarker
key={CHOOSE_UNIQUE_KEY_FOR_THIS_ITEM}
lat={geo.coordinates[1]}
lng={geo.coordinates[0]}
type='severeStorms'
onClick={() => setLocationInfo({ id: ev.id, title: ev.title })}
/>
);
});
}
return null;
});
You can read more about this here: https://reactjs.org/docs/lists-and-keys.html
Upvotes: 1