-2

import React, {
  useState
} from "react";

import GoogleMapReact from "google-map-react";

function GMap() {
  const [latLgn, setLatLgn] = useState([{
      lng: 24.7536,
      lat: 59.437
    },
    {
      lng: 24.7303,
      lat: 59.4393
    },
    {
      lng: 24.7387,
      lat: 59.4497
    },
  ]);
  const [tallinn] = useState({
    center: { // where i want to be centerd
      lng: 24.7536,
      lat: 59.437,
    },
    zoom: 10,
  });



  // Fit map to its bounds after the api is loaded
  const apiIsLoaded = (map, maps, latlgn) => {
    // Get bounds by our latlgn
    const bounds = getMapBounds(map, maps, latlgn);
    // Fit map to bounds
    map.fitBounds(bounds);
    // Bind the resize listener
    bindResizeListener(map, maps, bounds);
  };

  // Re-center map when resizing the window
  const bindResizeListener = (map, maps, bounds) => {
    maps.event.addDomListenerOnce(map, "idle", () => {
      maps.event.addDomListener(window, "resize", () => {
        map.fitBounds(bounds);
      });
    });
  };

  // Return map bounds based on list of places
  const getMapBounds = (map, maps, pins) => {
    const bounds = new maps.LatLngBounds();

    pins.forEach((pin) => {
      bounds.extend(new maps.LatLng(pin[1], pin[0]));
    });
    return bounds;
  };

  return ( <
    div >
    <
    div style = {
      {
        height: "100vh",
        width: "100%"
      }
    } >
    <
    GoogleMapReact bootstrapURLKeys = {
      {
        key: AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk
      }
    }
    defaultCenter = {
      tallinn.center
    }
    defaultZoom = {
      tallinn.zoom
    }
    onGoogleApiLoaded = {
      ({
        map,
        maps
      }) => apiIsLoaded(map, maps, latLgn)
    }
    yesIWantToUseGoogleMapApiInternals >
    {
      latLgn.map((item, index) => ( <
        div lat = {
          item[1]
        }
        lng = {
          item[0]
        }
        key = {
          index
        } > 
        </div>
      ))
    } </GoogleMapReact>
    </div> 
    </div>
  );
}
export default Gmap
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


I have a problem with centralizing the map I am rendering.
although I have a state with the "lat" and "lng" as stated in the docs still, when I run the app with npm start or refreshing the page, it will centre itself somewhere in the ocean.\

PS. I will paste my "map" component only.

import React, { useState } from "react";

import GoogleMapReact from "google-map-react";

export default function GMap() {
  const [latLgn, setLatLgn] = useState([{
      lng: 24.7536,
      lat: 59.437
    },
    {
      lng: 24.7303,
      lat: 59.4393
    },
    {
      lng: 24.7387,
      lat: 59.4497
    },
  ]);
  const [tallinn] = useState({
    center: { // where i want to be centerd
      lng: 24.7536,
      lat: 59.437,
    },
    zoom: 10,
  });

 

  // Fit map to its bounds after the api is loaded
  const apiIsLoaded = (map, maps, latlgn) => {
    // Get bounds by our latlgn
    const bounds = getMapBounds(map, maps, latlgn);
    // Fit map to bounds
    map.fitBounds(bounds);
    // Bind the resize listener
    bindResizeListener(map, maps, bounds);
  };

  // Re-center map when resizing the window
  const bindResizeListener = (map, maps, bounds) => {
    maps.event.addDomListenerOnce(map, "idle", () => {
      maps.event.addDomListener(window, "resize", () => {
        map.fitBounds(bounds);
      });
    });
  };

  // Return map bounds based on list of places
  const getMapBounds = (map, maps, pins) => {
    const bounds = new maps.LatLngBounds();

    pins.forEach((pin) => {
      bounds.extend(new maps.LatLng(pin[1], pin[0]));
    });
    return bounds;
  };

  return (
    <div>
      <div style={{ height: "100vh", width: "100%" }}>
        <GoogleMapReact
          bootstrapURLKeys={{key: AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk }}
          defaultCenter={tallinn.center}
          defaultZoom={tallinn.zoom}
          onGoogleApiLoaded={({ map, maps }) => apiIsLoaded(map, maps, latLgn)}
          yesIWantToUseGoogleMapApiInternals
        >
          {latLgn.map((item, index) => (
            <div lat={item[1]} lng={item[0]} key={index}< </div>
          ))}
        </GoogleMapReact>
      </div>
    </div>
  );
}

ps. let me know if I should provide more information

UPDATE

I have created a sample project here.

Kim-Jun-Un
  • 83
  • 2
  • 11
  • 1
    Please provide a [mcve] that demonstrates your issue, preferably a working [StackSnippet](https://meta.stackoverflow.com/questions/269753/feedback-requested-runnable-code-snippets-in-questions-and-answers) in the question itself. – geocodezip Aug 09 '21 at 12:40
  • @geocodezip, thanks for your reply. how can I make a working stackSnippet without sharing my google API key in public? – Kim-Jun-Un Aug 09 '21 at 13:31
  • Make the API key as .env variable (Follow https://create-react-app.dev/docs/adding-custom-environment-variables/ if you are not sure on that) and for reproducing, you can share as StackSnippet as @geocodezip mentioned so we will be able to see a run time/preview of what you are trying – MrSrv7 Aug 09 '21 at 14:41
  • 1
    @harry9345 There is a Google Test key available, which works on StackOverflow AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk (for the Google Maps Javascript API v3) – geocodezip Aug 09 '21 at 15:10
  • @geocodezip, I created the stackbiltz project. please have a look – Kim-Jun-Un Aug 16 '21 at 08:08

1 Answers1

0

I checked your code and I noticed a couple of things.

First, in your getMapBounds function, the bounds returned are null. This is because the values of pin[1] and pin[0] are undefined. This might be the reasoon why the map is centering in the middle of the ocean like this as this is the center of the world and coordinates are 0,0. You must use pin.lat and pin.lng instead so that it will correctly populate the value for bounds.

Second, it seems that you would like to put markers on the coordinates of your latLgn. To achieve this, you can follow the AnyReactComponent function as mentioned in the google-map-react docs instead of putting a div directly inside the latLgn.map.

Lastly, inside your latLgn.map, you must not use item[1] and item[0] as they are also both undefined instead use item.lat and item.lng.

Here's the code snippet for my working code:

import React, { useState } from "react";
import "./style.css"
import GoogleMapReact from "google-map-react";

const AnyReactComponent = ({ text }) => <div>{text}</div>;
export default function GMap() {
  const [latLgn, setLatLgn] = useState([{
      lng: 24.7536,
      lat: 59.437
    },
    {
      lng: 24.7303,
      lat: 59.4393
    },
    {
      lng: 24.7387,
      lat: 59.4497
    },
  ]);
  const [tallinn] = useState({
    center: { // where i want to be centerd
      lng: 24.7536,
      lat: 59.437,
    },
    zoom: 10,
  });

 

  // Fit map to its bounds after the api is loaded
  const apiIsLoaded = (map, maps, latlgn) => {
    // Get bounds by our latlgn
    const bounds = getMapBounds(map, maps, latlgn);
    // Fit map to bounds
    map.fitBounds(bounds);
    // Bind the resize listener
    bindResizeListener(map, maps, bounds);
  };

  // Re-center map when resizing the window
  const bindResizeListener = (map, maps, bounds) => {
    maps.event.addDomListenerOnce(map, "idle", () => {
      maps.event.addDomListener(window, "resize", () => {
        map.fitBounds(bounds);
      });
    });
  };

  // Return map bounds based on list of places
  const getMapBounds = (map, maps, pins) => {
    const bounds = new maps.LatLngBounds();

    pins.forEach((pin) => {
      bounds.extend(new maps.LatLng(pin.lat, pin.lng));
      console.log(pin[0])
    });
    return bounds;
  };

  return (
    <div>
      <div style={{ height: "100vh", width: "100%" }}>
        <GoogleMapReact
          bootstrapURLKeys={{key: "YOUR_API_KEY" }}
          defaultCenter={tallinn.center}
          defaultZoom={tallinn.zoom}
          onGoogleApiLoaded={({ map, maps }) => apiIsLoaded(map, maps, latLgn)}
          yesIWantToUseGoogleMapApiInternals
        >
        {latLgn.map((item, index) => (
            <AnyReactComponent lat={item.lat} lng={item.lng} key={index} text={"(" +item.lat  + "," + item.lng +")"}> </AnyReactComponent>
          ))}
        </GoogleMapReact>
      </div>
    </div>
  );
}

I also noticed your question in the comment section. You can use online ides like stackblitz to provide an sscce of your code and just remove the API key. You can put a note in your question that you need to put API key to see how the code works. You can refer to my working code above.

Pagemag
  • 2,779
  • 1
  • 7
  • 17
  • thanks a lot. First of all, I update the question and you can check the stackbiltz project for more. about your points: about " pin.lat and pin.lng " , as I didn't move all my code to here I hard code the state, otherwise the data coming from API is an array of objects and the lat and lng in an array in that object(have look at the stackbilts please). the div I use here was just to show. in real life, it's a component. your suggestion about " item.lat and item.lng." doesn't work too. Please have look at the project I created at stackblitz – Kim-Jun-Un Aug 16 '21 at 08:22
  • @harry9345, I seem to find the problem in your code. It appears that the issue is on the timing of the population of your `props`. In the App.js of your code you are getting the data every 5sec and it will populate the props then you are setting the bounds(getMapBounds) inside your apiIsLoaded. However, the problem on this is that the `latLgn` is still null when the apiIsLoaded function is trigger. The initial value of your bounds after instantiating it in getMapBounds is `{south: 1, west: 180, north: -1, east: -180…}` and since the pins value is `[]` it won't change after bounds.extend. – Pagemag Aug 16 '21 at 21:58
  • @harry9345 continuation: Going back to apiIsLoaded function, the bounds that it will pass will be `{south: 1, west: 180, north: -1, east: -180…}` and if you use map.fitBounds on this value of bounds it will set the center of the map to `{lat: 0, lng: 180}` which is in the middle of the [ocean](https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/utils/geocoder/#q%3D0%252C180). You need to find a way where you call the getMapBounds when the `latLgn` is already populated by props so that it will pass the coordinates instead of []. – Pagemag Aug 16 '21 at 22:02
  • Thanks a lot for your help @Pagemag, I got what you are talking about, I will try to fix it, Otherwise I will ask for help again. – Kim-Jun-Un Aug 18 '21 at 07:24
  • I accept your answer as the correct one as I figure out a way to solve this issue – Kim-Jun-Un Aug 30 '21 at 14:49