Replies: 8 comments
-
I think I have an Idea whats happening:
To mitigate, it should be enough to memoize the two callbacks you're passing to AdvancedMarker, which is a good practice anyway... const MarkerWithInfoWindow = forwardRef<
AdvancedMarkerRef,
AdvancedMarkerProps & {
point: Point;
setMarkerRef: (marker: Marker | null, key: number) => void;
}
>(({ point, setMarkerRef, ...props }, ref) => {
let [markerRef, marker] = useAdvancedMarkerRef();
const [infoWindowOpen, setInfoWindowOpen] = useState(false);
const refCallback = useCallback((marker1) => {
markerRef(marker1);
setMarkerRef(marker1, point.key);
}, [setMarkerRef, point.key]);
const handleClick = useCallback((e) => {
setInfoWindowOpen(true);
}, []);
return (
<>
<AdvancedMarker
ref={refCallback}
onClick={handleClick}
position={point}
title={point.name}
zIndex={50}
{...props}
/>
{infoWindowOpen && (
<InfoWindow anchor={marker} maxWidth={200} onCloseClick={() => setInfoWindowOpen(false)}>
<code style={{ whiteSpace: 'nowrap' }}><AdvancedMarker /></code> combined with an
Infowindow.
</InfoWindow>
)}
</>
);
}); |
Beta Was this translation helpful? Give feedback.
-
Great, i will check on it.. however its a bit of confusion that a ref update can cause re-render, since in react, refs are global to the component lifecycle and updating it should not re-render the component. Let me know if there misunderstanding on implementation of ref or how it should work ? |
Beta Was this translation helpful? Give feedback.
-
This case is slightly different – since we need to react to changing of the ref (update the anchor of the infowindow when the marker API-element is available), I'm always open to suggestions how to architect this differently, but as far as I am aware this is the best solution we have available to build the connection of the marker to the infowindow. |
Beta Was this translation helpful? Give feedback.
-
ah i see... This code is not directly related with export function useAdvancedMarkerRef() {
const [marker, setMarker] =
useState<google.maps.marker.AdvancedMarkerElement | null>(null);
const refCallback = useCallback((m: AdvancedMarkerRef | null) => {
setMarker(m);
}, []);
return [refCallback, marker] as const;
} the term Just my few cents:Can we store marker in const markerRef = useRef<google.maps.marker.AdvancedMarkerElement | null>(null);
const [infoWindowOpen, setInfoWindowOpen] = useState(false);
const refCallback = useCallback((marker) => {
markerRef.current = marker;
setMarkerRef(marker, point.key);
}, [setMarkerRef, point.key]);
const handleClick = useCallback((e) => {
setInfoWindowOpen(true);
}, []);
return (
<>
<AdvancedMarker
ref={refCallback}
onClick={handleClick}
position={point}
title={point.name}
zIndex={50}
{...props}
/>
{infoWindowOpen && markerRef.current && (
<InfoWindow anchor={markerRef.current} maxWidth={200} onCloseClick={() => setInfoWindowOpen(false)}>
<code style={{ whiteSpace: 'nowrap' }}><AdvancedMarker /></code> combined with an
Infowindow.
</InfoWindow>
)}
</>
) if you want to open the marker by default then use the |
Beta Was this translation helpful? Give feedback.
-
That's interesting to read and I understand the confusion. Originally, React only had the CallbackRef style refs, iirc the newer style (mutable object ref) that we now know as 'ref' was introduced together with hooks in 16.8, probably precisely because of the problems the callbacks can have. Still, both are valid formats for a ref. Your suggestion will probably work as well, but you the component will not notice when the ref'd object (the Also let me note that the documentation is pretty clear about not using
|
Beta Was this translation helpful? Give feedback.
-
Ah great explanation, thanks for pointing out the best practice. 🙏🏼 However, this was a bit ambiguous to understand, usually it always works or in my experience on mounted there's DOM available.
|
Beta Was this translation helpful? Give feedback.
-
just that: if the internal marker object in {infoWindowOpen && markerRef.current && ( ... ) } There'll be no re-render once it is available, so no way to recover from that. |
Beta Was this translation helpful? Give feedback.
-
I'll convert this to a discussion, it doesn't look like theres an actual bug in our library here. |
Beta Was this translation helpful? Give feedback.
-
Description
I am using the Cluster example the docs with MarkerWithInfoWindow, however there is nothing much i changed for cluster or infowindow from the docs... onClick on the marker should have open the infowindow, but instead to goes in an infinite loop.
Please note that i am setting the
markerRef(marker);
on the ref of AdvanceMarker manually because i want to support Cluster along with it... it appears to be a standard way to me to set ref to multiple places for marker... however it crashesSteps to Reproduce
I am using next 14, and this is a client component.
Environment
Logs
Beta Was this translation helpful? Give feedback.
All reactions