Closed RayPaez83 closed 2 years ago
+1 on this behavior with Overlay Views
Same here, with the official @react-google-maps/api
library and the provided overlay code snippet from https://react-google-maps-api-docs.netlify.app/#overlayview.
sandbox: https://codesandbox.io/s/simple-overlay-r3fky0
+1. I am currently working on a commercial project with this library and the issue occurs on React 18 when dragging ends. It seems to impact all OverlayViews. Downgrading to React 17 fixes the issue, but this is not an acceptable solution.
Good day everyone, here is a sandbox with an example using OverlayView and having the flashing issue: https://codesandbox.io/s/usememo-example-forked-vwfwrw
P.S.: Since the issue only happens with React v18, is maybe somehow related to the new "concurent renderer"? https://reactjs.org/blog/2022/03/29/react-v18.html#new-client-and-server-rendering-apis
@luisoliva1 There is multiple issues with your example. please do not store const in the component - move it out. Add performance optimizations with hooks and memo. Use eslint with plugins. eslint-plugin-react-perf is important to reduce re-renders. memo important to reduce re-renders too.
@luisoliva1 There is multiple issues with your example. please do not store const in the component - move it out. Add performance optimizations with hooks and memo. Use eslint with plugins. eslint-plugin-react-perf is important to reduce re-renders. memo important to reduce re-renders too.
How would you improve this example? you can't move the const isLoaded
out of the scope, because useLoadScript
is a react hook, or am I mistaken? And the other const values are not inside the component. The only thing one can store in a memo is the isLoaded ? <MapGoogle /> : <h1>Loading...</h1>
part. But that does not fix the flickering.
So I definitely think there there is a problem between react 18 and the @react-google-maps.
@JustFly1984 adding an OverlayView
the traditional way (extending google.maps.OverlayView
) and applying setMap(mapRef)
to it works fine.
Seems like a react problem.
The problem is class component itself. it require rewrite to functional component with hooks.
Working example adapted from DawChihLiou blog https://hackernoon.com/building-an-airbnb-like-map-in-nextjs It seems that the difference between the two is that the one from Daw has another nested div. In the image the Overlays are the components that have left and right styling.
Class logic
export function createOverlay(
container: HTMLElement,
pane: keyof google.maps.MapPanes,
position: google.maps.LatLng | google.maps.LatLngLiteral
) {
class Overlay extends google.maps.OverlayView {
container: HTMLElement
pane: keyof google.maps.MapPanes
position: google.maps.LatLng | google.maps.LatLngLiteral
constructor(
container: HTMLElement,
pane: keyof google.maps.MapPanes,
position: google.maps.LatLng | google.maps.LatLngLiteral
) {
super()
this.container = container
this.pane = pane
this.position = position
}
onAdd(): void {
const pane = this.getPanes()?.[this.pane]
pane?.appendChild(this.container)
}
draw(): void {
const projection = this.getProjection()
const point = projection.fromLatLngToDivPixel(this.position)
if (point === null) {
return
}
this.container.style.transform = `translate(${point.x}px, ${point.y}px)`
}
onRemove(): void {
if (this.container.parentNode !== null) {
this.container.parentNode.removeChild(this.container)
}
}
}
return new Overlay(container, pane, position)
}
Overlay Component
import { PropsWithChildren, useContext, useEffect, useMemo } from 'react'
import { createPortal } from 'react-dom'
import MapContext from '../../map-context'
import { createOverlay } from './Overlay'
type OverlayProps = PropsWithChildren<{
position: google.maps.LatLng | google.maps.LatLngLiteral
pane?: keyof google.maps.MapPanes
map: google.maps.Map
zIndex?: number
}>
export default function OverlayView({
position,
pane = 'floatPane',
zIndex,
children,
}: OverlayProps) {
const map = useContext(MapContext)
const container = useMemo(() => {
const div = document.createElement('div')
div.style.position = 'absolute'
return div
}, [])
const overlay = useMemo(() => {
return createOverlay(container, pane, position)
}, [container, pane, position])
useEffect(() => {
overlay?.setMap(map)
return () => overlay?.setMap(null)
}, [map, overlay])
// to move the container to the foreground and background
useEffect(() => {
container.style.zIndex = `${zIndex}`
}, [zIndex, container])
return createPortal(children, container)
}
Using OverlayViewF worked for me!
Issue template
The new react version 18 having some issues with the react google maps api on drag end.
https://codesandbox.io/s/googlemapreact-demo-forked-5gdsib
Please provide an explanation of the issue
We were working in this issue the last days and we found that it is an issue between React 18 and the maps library because as soon you downgrade the react version to the 17 the flickering issue disappears
Your Environment
os: mac/
node --version 14.7.1
react version 18
webpack version
@babel version
@react-google-maps/api version 2.12.1
How does it behave?
When you drag en finish this the overlayview content flickering.
How should it behave correctly?
The overlayview content should stay in the same spots where the developer place it
Basic implementation of incorrect behavior in codesandbox.com
This is not my code but is some one code who has the same issue
https://codesandbox.io/s/googlemapreact-demo-forked-5gdsib