I have developed a daycare application, so I want to display the daycare location on Google Maps. I've integrated Google Maps with the React application. When loading the application, it correctly shows the location. However, when dragging or zooming, my location also moves. The location should always remain the same.I am using node.js express as backend
https://app.screencastify.com/v3/watch/DltGBIYDwrZY0xlJw6v9
import React, { useState, useEffect } from "react";
import GoogleMapReact from 'google-map-react';
import { Icon } from "@iconify/react";
import locationIcon from "@iconify/icons-mdi/map-marker";
const LocationPin = ({ name }) => (
<div className="pin">
<Icon icon={locationIcon} className="pin-icon" />
<p className="pin-text">{name}</p>
</div>
);
const Map = ({ daycares }) => {
const [latitude, setLatitude] = useState(43.77887);
const [longitude, setLongitude] = useState(-79.17282);
useEffect(() => {
navigator.geolocation.getCurrentPosition(
(position) => {
setLatitude(position.coords.latitude);
setLongitude(position.coords.longitude);
},
(error) => {
console.error(error);
}
);
}, []); // Empty dependency array means this effect runs only once after the initial render
const renderMap = () => {
if (!daycares || daycares.length === 0) {
return null; // Return early if daycares is empty or undefined
}
return (
<div style={{ height: "80vh", width: "100%" }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "AIzaSyAzEQgX_hi-_Qnv6aWWIQDAdcLYnFPqQSQ" }}
defaultCenter={{
lat: latitude,
lng: longitude
}}
defaultZoom={12}
>
{daycares.map((daycare) => (
<LocationPin
key={daycare.id}
lat={parseFloat(daycare.latitude)}
lng={parseFloat(daycare.longitude)}
name={daycare.childcare_name}
/>
))}
</GoogleMapReact>
</div>
);
};
return (
<div>
{renderMap()}
</div>
);
};
export default Map;
const LocationPin = ({ lat, lng, name }) => (
<div className="pin" style={{ position: 'absolute', transform: 'translate(-50%, -50%)' }}>
<Icon icon={locationIcon} className="pin-icon" />
<p className="pin-text">{name}</p>
</div>
);
export default LocationPin;
The location should always remain the same
My mock Data:
{
childcare_name: "East Side Preschool",
address: "458 Fairall Street",
city: "Ajax",
region: "Ontario",
postalcode: " L1S 1R6",
country: "CANADA",
latitude: "43.75991",
longitude: "-79.18827",
owner_name: "Jessica Lee",
age_range: "2-6",
years: "4",
infant_capacity: "8",
toddler_capacity: "12",
preschool_capacity: "18",
contact_phone: "555-9012",
contact_email: "jessica@example.com",
},
{
childcare_name: "Kepalen Angelic Child Care Daycare",
address: "1301 Neilson Rd",
city: "Scarborough",
region: "Ontario",
postalcode: "M1B 3C2",
country: "Canada",
latitude: "43.80716",
longitude: "-79.21856",
owner_name: "Nabhila",
age_range: "0-6",
years: "3",
infant_capacity: "15",
toddler_capacity: "20",
preschool_capacity: "25",
contact_phone: "555-1357",
contact_email: "nabila@example.com",
},
As I have suggested on my comment on your question, you should just use a different library that supports Advanced Markers. Since Advanced Markers allows you to load a marker purely as an HTML element.
In this case, I'd recommend that you use @vis.gl/react-google-maps
and its respective <AdvancedMarker>
Component.
To implement it, you should just follow the documentation of the aforementioned library on how to load a map and an advanced marker.
Then to use it with your data, you should utilize the array.map()
when loading the markers. Which would iterate through your data and use those data to pass into your AdvancedMarker component rendering. Your code should look something like this:
import React from "react";
import { createRoot } from "react-dom/client";
import { AdvancedMarker, APIProvider, Map } from "@vis.gl/react-google-maps";
const API_KEY =
globalThis.GOOGLE_MAPS_API_KEY ?? (process.env.GOOGLE_MAPS_API_KEY as string);
const App = () => {
var childCareData = [
{
childcare_name: "East Side Preschool",
address: "458 Fairall Street",
city: "Ajax",
region: "Ontario",
postalcode: " L1S 1R6",
country: "CANADA",
latitude: "43.75991",
longitude: "-79.18827",
owner_name: "Jessica Lee",
age_range: "2-6",
years: "4",
infant_capacity: "8",
toddler_capacity: "12",
preschool_capacity: "18",
contact_phone: "555-9012",
contact_email: "jessica@example.com",
},
{
childcare_name: "Kepalen Angelic Child Care Daycare",
address: "1301 Neilson Rd",
city: "Scarborough",
region: "Ontario",
postalcode: "M1B 3C2",
country: "Canada",
latitude: "43.80716",
longitude: "-79.21856",
owner_name: "Nabhila",
age_range: "0-6",
years: "3",
infant_capacity: "15",
toddler_capacity: "20",
preschool_capacity: "25",
contact_phone: "555-1357",
contact_email: "nabila@example.com",
},
];
return (
<APIProvider apiKey={API_KEY} libraries={["marker"]}>
<Map
mapId={"bf51a910020fa25a"}
defaultZoom={12}
defaultCenter={{ lat: 43.77887, lng: -79.17282 }}
gestureHandling={"greedy"}
disableDefaultUI
>
{childCareData &&
childCareData.map((childCare, key) => {
/* Convert your longitude and latitude into a float first
since your data stored it as a string. */
const floatLat = parseFloat(childCare.latitude);
const floatLng = parseFloat(childCare.longitude);
return (
<AdvancedMarker
key={key}
position={{ lat: floatLat, lng: floatLng }}
title={"AdvancedMarker with custom html content."}
>
<div
style={{
width: 16,
height: 16,
position: "absolute",
background: "#1dbe80",
border: "2px solid #0e6443",
borderRadius: "50%",
transform: "translate(-50%, -50%)",
}}
>
<h3
style={{
padding: 12,
}}
>
{childCare.childcare_name}
</h3>
</div>
</AdvancedMarker>
);
})}
</Map>
</APIProvider>
);
};
export default App;
export function renderToDom(container: HTMLElement) {
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
}
Then this should work as expected without the issue of locations following around as you move the map.
Here's a proof of concept codesandbox that you can try out and check yourself.