ErrorPro / react-google-autocomplete

React components for google places API.
MIT License
462 stars 114 forks source link

On next.js it works on localhost, but in production getting random errors #190

Open Katanis opened 1 year ago

Katanis commented 1 year ago

Hello, so we implemented google autocomplete in our project, we have two similar projects one is with create-react-app another is with next.js we use the same component. We run into problems when the code goes in prod, or if we build and run the project locally, autocomplete does not work and console shows random errors and react-google-autocomplete does not work. Uncaught SyntaxError: Identifier 'B' has already been declared (at 5867.5af1d63e943940b9.js:1:1041)

This is the component of GoogleAddressAutocomplete

import React from 'react';
import { useState } from 'react';
import usePlacesService from 'react-google-autocomplete/lib/usePlacesAutocompleteService';
import { useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import { getEnv } from '@app/env/getEnv';
import { useTenantProps } from '@app/tenants/TenantPropsContext';
import {
  Autocomplete,
  CircularProgress,
  TextField as MuiTextField,
} from '@mui/material';

interface GoogleAddressComponent {
  long_name: string;
  short_name: string;
  types: string[];
}

export const GoogleAddressAutocomplete: React.FC = () => {
  const [open, setOpen] = useState(false);
  const { t } = useTranslation('pos');
  const env = getEnv();
  const { tenant } = useTenantProps();
  const {
    placesService,
    placePredictions,
    getPlacePredictions,
    isPlacePredictionsLoading,
  } = usePlacesService({
    apiKey:
      env.client.clientTenantSecrets?.[tenant.config.setup.name].googleApiKey,
    debounce: 1000,
  });
  const { setValue } = useFormContext();

  return (
    <Autocomplete
      onInputChange={(_, val) => getPlacePredictions({ input: val })}
      onChange={(_, val, reason) => {
        if (reason === 'selectOption') {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          placesService.getDetails({ placeId: val.place_id }, (details: any) =>
            setCustomerAddress(details)
          );
        }
      }}
      open={open}
      onOpen={() => {
        setOpen(true);
      }}
      onClose={() => {
        setOpen(false);
      }}
      isOptionEqualToValue={(option, value) => option.description === value}
      getOptionLabel={(option) => option.description}
      options={placePredictions}
      loading={isPlacePredictionsLoading}
      renderInput={(params) => (
        <MuiTextField
          {...params}
          label={t(
            'plans:stepper.personalInfo.form.label.deliveryAddress.location'
          )}
          variant="standard"
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <React.Fragment>
                {isPlacePredictionsLoading ? (
                  <CircularProgress color="inherit" size={20} />
                ) : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
        />
      )}
    />
  );

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  function setCustomerAddress(selectedLocation: any) {
    const addressComponent: GoogleAddressComponent[] =
      selectedLocation.address_components;
    setValue('address', {
      city: '',
      zipCode: '',
      region: '',
      district: '',
      addressLine1: '',
    });
    addressComponent.forEach((address) => {
      if (address.types.includes('postal_code')) {
        setValue('address.zipCode', address.short_name);
        return;
      }
      if (
        address.types.includes('postal_town') ||
        address.types.includes('locality')
      ) {
        setValue('address.city', address.short_name);
        return;
      }
      if (address.types.includes('administrative_area_level_1')) {
        setValue('address.region', address.short_name);
        return;
      }
      if (address.types.includes('administrative_area_level_2')) {
        setValue('address.district', address.short_name);
        return;
      }
    });
    const route =
      addressComponent.find((address) => address.types.includes('route'))
        ?.short_name ?? '';
    const streetNumber = addressComponent.find((address) =>
      address.types.includes('street_number')
    )?.short_name;
    const fullAddress = streetNumber ? `${route} ${streetNumber}` : route;
    setValue('address.addressLine1', fullAddress);
  }
};