1

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;


3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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;

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.