Skip to content

Commit

Permalink
fix(autocomplete-address): prevent infinite loop when initial address…
Browse files Browse the repository at this point in the history
… is not provided
  • Loading branch information
talo242 committed Sep 15, 2023
1 parent 4606951 commit dbbfeaf
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 86 deletions.
74 changes: 41 additions & 33 deletions src/lib/components/autocompleteAddress/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,55 @@ const story = {
address: {
description: 'The address properties',
table: {
type: {
summary: 'Partial<Address>'
type: {
summary: 'Partial<Address>',
},
},
},
apiKey: {
defaultValue: 'AIzaSyDg0DSrjYKt5smmsjkVasDz7c4T5rbOXT8',
description: 'Your private API key for the [Google Places API](https://developers.google.com/maps/documentation/places/web-service/overview)',
description:
'Your private API key for the [Google Places API](https://developers.google.com/maps/documentation/places/web-service/overview)',
table: {
type: {
summary: 'Partial<Address>'
type: {
summary: 'Partial<Address>',
},
},
},
onAddressChange: {
description: 'Callback with the updated address, this function will get called everytime the address gets updated',
description:
'Callback with the updated address, this function will get called everytime the address gets updated',
action: true,
table: {
category: "Callbacks",
category: 'Callbacks',
},
},
manualAddressEntryTexts: {
description: 'The CTA that enables manual address entry and the text preceding it',
description:
'The CTA that enables manual address entry and the text preceding it',
table: {
type: {
summary: '{ preText?: string; cta: string?; }'
}
}
summary: '{ preText?: string; cta: string?; }',
},
},
},
placeholders: {
description: 'Placeholder text',
table: {
type: {
summary: '{ manualAddressEntry?: string; street: string?; houseNumber?: string; additionalInformation?: string; postcode?: string; city?: string; }'
}
}
}
summary:
'{ manualAddressEntry?: string; street: string?; houseNumber?: string; additionalInformation?: string; postcode?: string; city?: string; }',
},
},
},
},
parameters: {
componentSubtitle: 'Autocomplete Address are user interface elements which allow users start typing an address and get autocompletion suggestions on the address.',
componentSubtitle:
'Autocomplete Address are user interface elements which allow users start typing an address and get autocompletion suggestions on the address.',
docs: {
description: {
component: 'This component is for now only restricted to "address" types and will restrict every query to Germany.',
component:
'This component is for now only restricted to "address" types and will restrict every query to Germany.',
},
},
customTypes: {
Expand All @@ -62,8 +68,8 @@ const story = {
city: string;
additionalInformation?: string;
country: string;
}`
}
}`,
},
},
};

Expand All @@ -74,9 +80,11 @@ export const AutocompleteAddressStory = ({
onAddressChange,
placeholders,
}: AutocompleteAddressProps) => {
const [address, setAddress] = useState<Partial<Address> | undefined>(defaultAddress);
const [address, setAddress] = useState<Partial<Address> | undefined>(
defaultAddress
);
const handleOnAddressChange = (newAddress: Partial<Address>) => {
onAddressChange(newAddress);
onAddressChange?.(newAddress);
setAddress(newAddress);
};

Expand All @@ -91,24 +99,24 @@ export const AutocompleteAddressStory = ({
);
};

AutocompleteAddressStory.storyName = "AutocompleteAddress";
AutocompleteAddressStory.storyName = 'AutocompleteAddress';

export const WithAddress = ({
apiKey,
onAddressChange,
placeholders,
}: AutocompleteAddressProps) => (
<AutocompleteAddress
address={{
street: 'Lohmuehlenstraße',
houseNumber: '65',
city: 'Berlin',
country: 'DE',
additionalInformation: 'c/o Factory',
}}
apiKey={apiKey}
onAddressChange={onAddressChange}
/>
<AutocompleteAddress
address={{
street: 'Lohmuehlenstraße',
houseNumber: '65',
city: 'Berlin',
country: 'DE',
additionalInformation: 'c/o Factory',
}}
apiKey={apiKey}
onAddressChange={onAddressChange}
/>
);

export const WithLocalisationEntryText = ({
Expand Down
108 changes: 55 additions & 53 deletions src/lib/components/autocompleteAddress/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import debounce from 'lodash.debounce';
import isEqual from 'lodash.isequal';
import { Input } from '../input';
import {
Address,
countryNameFromAlphaCode,
Alpha2CountryCode,
countryNameFromAlphaCode,
} from '@popsure/public-models';

import { geocoderAddressComponentToPartialAddress } from './util';
Expand Down Expand Up @@ -53,6 +52,23 @@ export interface AutocompleteAddressProps {
apiKey: string;
address?: Partial<Address>;
onAddressChange: (address: Partial<Address>) => void;
inputProps?: {
street?: {
name?: string;
};
houseNumber?: {
name?: string;
};
additionalInformation?: {
name?: string;
};
postcode?: {
name?: string;
};
city?: {
name?: string;
};
};
placeholders?: {
manualAddressEntry?: string;
street?: string;
Expand All @@ -73,6 +89,7 @@ const AutocompleteAddress = ({
onAddressChange,
placeholders,
manualAddressEntryTexts,
inputProps,
}: AutocompleteAddressProps) => {
const [manualAddressEntry, setManualAddressEntry] = useState(false);
const [isLoading, setIsLoading] = useState(false);
Expand All @@ -99,15 +116,12 @@ const AutocompleteAddress = ({
autocompleteElement.current.value = address.street;
}

if (isEqual(address, initialAddress) === false) {
onAddressChange({ ...address });
}
handleEnterAddressManually();
}
}, [initialAddress, address, onAddressChange, hasLoadedGoogleAPI]);
}, [address, onAddressChange, hasLoadedGoogleAPI]);

useEffect(() => {
if (hasLoadedGoogleAPI === false) {
if (!hasLoadedGoogleAPI) {
return;
}

Expand Down Expand Up @@ -156,6 +170,7 @@ const AutocompleteAddress = ({
...geocoderAddress,
additionalInformation: oldValue?.additionalInformation,
}));
onAddressChange?.(geocoderAddress);
}

map.current?.panTo(newPlace.geometry.location);
Expand Down Expand Up @@ -204,12 +219,28 @@ const AutocompleteAddress = ({
[]
);

const debouncedSetPlace = debounce(setPlaceFromAddress, 1000);
const debouncedSetPlace = debounce(setPlaceFromAddress, 2000);

const handleEnterAddressManually = () => {
setManualAddressEntry(true);
};

const onManualAddressChange =
({ updatePlace } = { updatePlace: true }) =>
(e: ChangeEvent<HTMLInputElement>) => {
const newAddress = {
...address,
[e.target.name]: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
onAddressChange(newAddress);

if (updatePlace) {
debouncedSetPlace(newAddress);
}
};

return (
<>
<div
Expand Down Expand Up @@ -257,31 +288,19 @@ const AutocompleteAddress = ({
type="text"
placeholder={placeholders?.street || 'Street'}
value={address?.street || ''}
onChange={(e) => {
const newAddress = {
...address,
street: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
debouncedSetPlace(newAddress);
}}
onChange={onManualAddressChange()}
name="street"
{...inputProps?.street}
/>
<Input
className={`wmx2 ${styles['house-number-input']}`}
data-cy="autocomplete-house-number"
key="autocomplete-house-number"
placeholder={placeholders?.houseNumber || 'House Number'}
value={address?.houseNumber || ''}
onChange={(e) => {
const newAddress = {
...address,
houseNumber: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
debouncedSetPlace(newAddress);
}}
name="houseNumber"
onChange={onManualAddressChange()}
{...inputProps?.houseNumber}
/>
</div>
<Input
Expand All @@ -293,14 +312,9 @@ const AutocompleteAddress = ({
'Additional information (C/O, apartment, …)'
}
value={address?.additionalInformation || ''}
onChange={(e) => {
const newAddress = {
...address,
additionalInformation: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
}}
name="additionalInformation"
onChange={onManualAddressChange({ updatePlace: false })}
{...inputProps?.additionalInformation}
/>
<div className={`d-flex mt16 c-gap16 ${styles['input-line']}`}>
<Input
Expand All @@ -309,31 +323,19 @@ const AutocompleteAddress = ({
key="autocomplete-postcode"
placeholder={placeholders?.postcode || 'Postcode'}
value={address?.postcode || ''}
onChange={(e) => {
const newAddress = {
...address,
postcode: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
debouncedSetPlace(newAddress);
}}
name="postcode"
onChange={onManualAddressChange()}
{...inputProps?.postcode}
/>
<Input
className="w100"
data-cy="autocomplete-city"
key="autocomplete-city"
placeholder={placeholders?.city || 'City'}
value={address?.city || ''}
onChange={(e) => {
const newAddress = {
...address,
city: e.target.value,
country: GERMANY_ALPHA_CODE,
};
setAddress(newAddress);
debouncedSetPlace(newAddress);
}}
name="city"
onChange={onManualAddressChange()}
{...inputProps?.city}
/>
</div>
</>
Expand Down

0 comments on commit dbbfeaf

Please sign in to comment.