Skip to content

Commit 94826a4

Browse files
committed
fix(infowindow): replace useDeepCompareEffect with useEffect
Due to the destructuring assignment of infowindowOptions, the useDeepCompareEffect was used to avoid re-assigning options even if they didn't change. This, however, caused serious problems with other dependencies of those effects that could contain cycles and large object-structures to be compared. Instead of `useDeepCompareEffect` this switches to using regular effects and deep memoization for the infowindowOptions.
1 parent 01f78e1 commit 94826a4

10 files changed

+47
-27
lines changed

src/components/info-window.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import React, {
99
useState
1010
} from 'react';
1111
import {createPortal} from 'react-dom';
12+
import isDeepEqual from 'fast-deep-equal';
1213

1314
import {useMap} from '../hooks/use-map';
1415
import {useMapsEventListener} from '../hooks/use-maps-event-listener';
15-
import {setValueForStyles} from '../libraries/set-value-for-styles';
1616
import {useMapsLibrary} from '../hooks/use-maps-library';
17-
import {useDeepCompareEffect} from '../libraries/use-deep-compare-effect';
17+
import {useMemoized} from '../hooks/use-memoized';
18+
import {setValueForStyles} from '../libraries/set-value-for-styles';
1819
import {CustomMarkerContent, isAdvancedMarker} from './advanced-marker';
1920

2021
export type InfoWindowProps = Omit<
@@ -56,7 +57,7 @@ export const InfoWindow: FunctionComponent<
5657
onCloseClick,
5758

5859
// other options
59-
...infoWindowOptions
60+
...volatileInfoWindowOptions
6061
} = props;
6162

6263
// ## create infowindow instance once the mapsLibrary is available.
@@ -68,6 +69,8 @@ export const InfoWindow: FunctionComponent<
6869
const contentContainerRef = useRef<HTMLElement | null>(null);
6970
const headerContainerRef = useRef<HTMLElement | null>(null);
7071

72+
const infoWindowOptions = useMemoized(volatileInfoWindowOptions, isDeepEqual);
73+
7174
useEffect(
7275
() => {
7376
if (!mapsLibrary) return;
@@ -118,8 +121,9 @@ export const InfoWindow: FunctionComponent<
118121
[mapsLibrary]
119122
);
120123

121-
// ## update className and styles for `contentContainer`
122-
// stores previously applied style properties, so they can be removed when unset
124+
// ---- update className and styles for `contentContainer`
125+
// prevStyleRef stores previously applied style properties, so they can be
126+
// removed when unset
123127
const prevStyleRef = useRef<CSSProperties | null>(null);
124128
useEffect(() => {
125129
if (!infoWindow || !contentContainerRef.current) return;
@@ -136,8 +140,8 @@ export const InfoWindow: FunctionComponent<
136140
contentContainerRef.current.className = className || '';
137141
}, [infoWindow, className, style]);
138142

139-
// ## update options
140-
useDeepCompareEffect(
143+
// ---- update options
144+
useEffect(
141145
() => {
142146
if (!infoWindow) return;
143147

@@ -172,7 +176,7 @@ export const InfoWindow: FunctionComponent<
172176

173177
// ## open info window when content and map are available
174178
const map = useMap();
175-
useDeepCompareEffect(() => {
179+
useEffect(() => {
176180
// `anchor === null` means an anchor is defined but not ready yet.
177181
if (!map || !infoWindow || anchor === null) return;
178182

src/components/map/use-map-instance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Ref, useEffect, useRef, useState} from 'react';
33
import {MapProps} from '../map';
44
import {APIProviderContextValue} from '../api-provider';
55

6-
import {useCallbackRef} from '../../libraries/use-callback-ref';
6+
import {useCallbackRef} from '../../hooks/use-callback-ref';
77
import {useApiIsLoaded} from '../../hooks/use-api-is-loaded';
88
import {
99
CameraState,

src/components/map/use-map-options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {MapProps} from '../map';
2-
import {useDeepCompareEffect} from '../../libraries/use-deep-compare-effect';
2+
import {useDeepCompareEffect} from '../../hooks/use-deep-compare-effect';
33

44
const mapOptionKeys: Set<keyof google.maps.MapOptions> = new Set([
55
'backgroundColor',

src/components/map/use-tracked-camera-state-ref.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {MutableRefObject, useEffect, useRef} from 'react';
2-
import {useForceUpdate} from '../../libraries/use-force-update';
2+
import {useForceUpdate} from '../../hooks/use-force-update';
33

44
export type CameraState = {
55
center: google.maps.LatLngLiteral;
File renamed without changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {DependencyList, EffectCallback, useEffect} from 'react';
2+
import {useMemoized} from './use-memoized';
3+
4+
export function useCustomCompareEffect<T extends DependencyList>(
5+
effect: EffectCallback,
6+
dependencies: T,
7+
isEqual: (a: T, b: T) => boolean
8+
) {
9+
// eslint-disable-next-line react-hooks/exhaustive-deps
10+
useEffect(effect, [useMemoized(dependencies, isEqual)]);
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {DependencyList, EffectCallback} from 'react';
2+
import {useCustomCompareEffect} from './use-custom-compare-efffect';
3+
import isDeepEqual from 'fast-deep-equal';
4+
5+
export function useDeepCompareEffect(
6+
effect: EffectCallback,
7+
dependencies: DependencyList
8+
) {
9+
useCustomCompareEffect(effect, dependencies, isDeepEqual);
10+
}
File renamed without changes.

src/hooks/use-memoized.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {useRef} from 'react';
2+
3+
export function useMemoized<T>(value: T, isEqual: (a: T, b: T) => boolean): T {
4+
const ref = useRef<T>(value);
5+
6+
if (!isEqual(value, ref.current)) {
7+
ref.current = value;
8+
}
9+
10+
return ref.current;
11+
}

src/libraries/use-deep-compare-effect.tsx

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)