I need to prevent my Google Map from reverting to its original center and zoom settings every time its parent component re-renders.
I have a parent component that contains two main child components: a Google Map and a sidebar. On the screen it looks like this:
My intention is to populate the sidebar with information when a particular marker is clicked. Here's the code:
PARENT:
import React, { useState } from "react";
import { styled } from "@mui/material/styles";
import MapComponent from "../Components/Map2";
export default function ACA() {
const [info, setInfo] = useState(null);
const FlexContainer = styled("div")(({ theme }) => ({
width: "98vw",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
padding: 4,
[theme.breakpoints.down("md")]: {
flexDirection: "column",
},
}));
const updateSidebar = (elec) => {
setInfo(elec);
};
return (
<div
style={{
minHeight: "100vh",
minWidth: "100vw",
background: "linear-gradient(to bottom, black, midnightblue)",
display: "flex",
flexDirection: "column",
alignItems: "center",
paddingTop: 10,
}}
>
<FlexContainer>
<MapComponent updateSidebar={updateSidebar} />
<div
style={{
height: "650px",
maxHeight: "80vh",
width: "650px",
maxWidth: "98vw",
border: "2px solid black",
backgroundColor: "whitesmoke",
borderRadius: 8,
}}
>
<h4>{info}</h4>
</div>
</FlexContainer>
</div>
);
}
MAPCOMPONENT
import React, { useEffect, useState } from "react";
import { APIProvider, Map, AdvancedMarker } from "@vis.gl/react-google-maps";
import Axios from "axios";
export default function MapComponent({ updateSidebar }) {
const [markers, setMarkers] = useState([]);
useEffect(() => {
const getElectorates = async () => {
try {
const elecs = await Axios.get("http://localhost:3930/admin/getMapData");
setMarkers(elecs.data);
} catch (err) {
console.log(err);
}
};
getElectorates();
}, []);
return (
<APIProvider apiKey="<redacted>">
<Map
style={{
width: "650px",
height: "650px",
maxWidth: "80vw",
maxHeight: "80vh",
}}
defaultCenter={{ lat: -23.698, lng: 133.8807 }}
defaultZoom={4}
gestureHandling={"greedy"}
disableDefaultUI={true}
mapId="<redacted>"
>
{markers.map((el, i) => {
return (
<AdvancedMarker
position={el.coords}
key={i}
onClick={() => {
updateSidebar(el.electorate);
}}
/>
);
})}
</Map>
</APIProvider>
);
}
The issue is that whenever I click on a marker and execute the updateSidebar function, the parent component's state is updated which in turn causes the map to revert to its original center and zoom settings. How can I prevent this from happening?

You should define your
FlexContainercomponent outside your parent componentThere's nothing wrong with your implementation of the
MapComponent. But from what I can see from your code, you have definedFlexContainerwithin your main componentACAlike so:Wherein you also returned it within the
ACAcomponent:This causes your
FlexContainerto be redefined everytime the main component gets rerendered. Because of it, everything else inside it gets redefined and rebuilt also. That's why yourMapComponentresets to its original state.To fix this, you must define
FlexContaineroutside of your main/parent componentACA. In this way, your FlexContainer is already defined regardless of how many times your parent component rerenders. Then this would not also cause yourMapComponentto be rebuilt from scratch.With that said, your parent component's code should look something like this:
Then this should fix your issue.
Here's a proof of concept codesandbox that you can try and test out yourself.