JustFly1984 / react-google-maps-api

React Google Maps API
MIT License
1.78k stars 437 forks source link

Map instance not updated during re-render? #3118

Open noobjun opened 1 year ago

noobjun commented 1 year ago

Problem

I notice that if component is re-rendered during panning/dragging, the map instance doesn't seem have to update its values (for example, center.lat(), center.lng() would still have old values).

Reproduce

Start dragging map on the marker, due to onMouseOver and onMouseOut, it will trigger a component rerender, you will see the map center snap back to its old values. (I tried to update center with onDragEnd, but it doesn't help, since map instance doesn't have correct center values) Note that if dragging doesn't start on the marker, then everything behaves correctly.

dragmarker

Sandbox

https://codesandbox.io/s/react-google-maps-api-re-render-while-dragging-18opbk?file=/src/index.js:0-1672

Your Environment

os: mac react: 16.8.1 @react-google-maps/api: 1.2.3

JustFly1984 commented 1 year ago

@noobjun Please use eslint with eslint-plugin-react-perf. This library is very sensitive to new objects/arrays/functions passed to props directly. As I see your example, it is all over the place. Please divide your app into smaller components.

pankajboruah commented 1 year ago

Hi @noobjun,

I think this is what's happening with your example:

The dragEnd event fires when you lift your mouse up after dragging. Also, if the cursor has moved out of the marker, onMouseOut is fired, which is causing the App to rerender.

So while you are dragging keeping your cursor over the marker, the center has not yet changed because dragEnd hasn't fired. If you move the mouse quickly(while dragging) outside the marker, the component rerenders with the previous center values. Then if you lift the mouse, dragEnd would fire. But since the center is same as when you started dragging center.lat() and center.lng() give the same values and the values are set to the state.

Also, I see that you have set center={{ lat: center.lat, lng: center.lng }}. On each App rerender, it creates a new reference { lat: center.lat, lng: center.lng } and passes it as a prop to GoogleMap which causes it to rerender even if the values are same. You should simply pass your center state as the prop.

In my project, I have stored the center inside ref instead of state, as I don't want to rerender on each center change event.