Google autocomplete hook state value is getting reset on function call

Viewed 79

Calling a prop function onLocationSelect from usePlacesWidget from react google autocomplete in Location.js. All the state values i.e serviceWindowData and routes when accessed inside onLocationSelect in parent i.e handleValueChange are empty/reset to it's initial state i.e in index.js

Printing in testFunc() values are empty, In developer tool i can see the value.

This issue is happening only for this call, For all other onChange events i am not facing this issue. Have hit a road block from 3 days, Please help me out.

Location.js

import React from 'react'
import { usePlacesWidget } from 'react-google-autocomplete'

const Location = ({
  error = false,
  errorMessage = '',
  onLocationSelect,
  placeholder = 'To',
  disabled,
  defaultValue,
}) => {
  const { ref } = usePlacesWidget({
    apiKey: process.env.NEXT_PUBLIC_GOOGLE_API_KEY,
    onPlaceSelected: (place) => {
      onLocationSelect(place, ref.current.value)
    },
    options: {
      types: ['geocode', 'establishment'],
      // types: ['(regions)'],
      componentRestrictions: { country: 'us' },
    },
  })

  const handleOnBlur = () => {
    if (!ref.current.value) {
      onLocationSelect(!ref.current.value)
    }
  }
  return (
    <div className="w-full">
      <div className="relative mb-4">
        <label className={'dropdown_field'}>
          <input
            ref={ref}
            placeholder={' '}
            disabled={disabled}
            defaultValue={defaultValue}
            onBlur={handleOnBlur}
          />
          <span className="label_bl">{placeholder}</span>
        </label>
        <div
          className={
            error
              ? 'bl-input__helper-text bl-input__helper-text--error'
              : 'bl-input__helper-text'
          }
        >
          {errorMessage}
        </div>
        <img
          src="/media/ic_place.svg"
          alt="place"
          className="absolute top-4 right-4"
        />
      </div>
    </div>
  )
}

export default Location

index.js

import { useState, useEffect } from "react";
import { PrimaryBtn } from "../../../lib/button/Button";
import DateInput from "../../TrainSearchWidget/dateinput";
import { changeDateFormat } from "../../../utilities/helperFunctions";
import DateComponent from "../DateComponent";
import { trainSearchWidget } from "constants/trainSearchWidget";
import Location from "components/Forms/Location";
import PassengerDropDown from "components/BrightlinePlus/PassengersDropdown";
import { d2dPassengers } from "constants/brightlineplus";
import TimePicker from "components/BrightlinePlus/TimePicker.js";
import moment from "moment";
import { DATE_FORMAT } from "utilities/Constants";
import Geocode from "react-geocode";
import { fetchServiceWindow } from "services/product";
import { useUser } from "../../../store/User";

const FROM = "From";
const TO = "To";
const Door2DoorService = ({
  data,
  isPlusDetailPage = false,
  callback,
  dateCompClass = "lg:left-44p",
  loading,
}) => {
  const user = useUser();
  const [serviceWindowData, setServiceWindowData] = useState([]);
  const [routes, setRoutes] = useState([]);

  const [errors, setErrors] = useState({
    origin: { error: false, errorMessage: "" },
    destination: { error: false, errorMessage: "" },
  });

  const [showDateRange, setShowDateRange] = useState(false);
  const [dateValue, setDateValue] = useState();
  const [passengersOptions, setPassengersOptions] = useState(
    d2dPassengers.passengers
  );
  const [serviceOptions, setServiceOptions] = useState(
    d2dPassengers.serviceRequests
  );
  const dateRangeToggle = (val) => {
    setShowDateRange(val);
  };

  useEffect(() => {
    getServiceData();
  },[]);
  useEffect(() => {
    if (!isPlusDetailPage) {
      if (navigator.geolocation) {
        const options = {
          enableHighAccuracy: true,
        };
        Geocode.setApiKey(process.env.NEXT_PUBLIC_GOOGLE_API_KEY);
        navigator.geolocation.getCurrentPosition(
          function (position) {
            let newData = d2dData.origin;
            newData.lat = position.coords.latitude;
            newData.lng = position.coords.longitude;
            setD2dData((prev) => {
              return { ...prev, origin: newData };
            });
            Geocode.fromLatLng(
              position.coords.latitude,
              position.coords.longitude
            ).then(
              (response) => {
                const address = response.results[0].formatted_address;
                let newData = d2dData.origin;
                newData.address = address;
                setD2dData((prev) => {
                  return { ...prev, origin: newData };
                });
              },
              (error) => {
                console.error(error);
              }
            );
          },
          function (err) {
            console.error(err?.message);
          },
          options
        );
      } else {
        // error case
      }
    }
  }, []);

  const getServiceData = async () => {
    let res = await fetchServiceWindow();
    setServiceWindowData(res?.data);
    console.log(res?.data);
  };

  const swapDestinations = () => {
    setD2dData((prev) => {
      return {
        ...prev,
        origin: d2dData.destination,
        destination: d2dData.origin,
      };
    });
  };

  const handleValueChange = (value, type) => {
    let data = d2dData[type];
    data.lat = value?.geometry?.location?.lat();
    data.lng = value?.geometry?.location?.lng();
    data.address = value?.formatted_address;
    console.log(type === "origin");
    console.log(data.lat);
    console.log(data.lng);
    if (type === "origin" && data.lat && data.lng) {
      testFunc();
      // let res = getNearestFromStationUsingDistanceMatrix();
    }
    setD2dData((prev) => {
      return { ...prev, [type]: data };
    });
    dateRangeToggle(false);
  };

  const testFunc = () => {
    console.log(serviceWindowData);
    console.log(routes);
  };

  return (
    <>
      <div
        className={`text-base text-bl-black pt-px ${
          isPlusDetailPage && "hidden"
        }`}
      >
        {
          "Enjoy a door-to-door experience. Brightline+ includes your train ride + transportation to and from the station."
        }
      </div>
      <div
        className={`grid lg:gap-3 lg:pt-0-938 relative ${
          isPlusDetailPage ? "grid-cols-6" : "grid-cols-5"
        }`}
      >
        <div className="col-span-12 mb-2 mt-4 relative lg:m-0 lg:col-span-1">
          <Location
            error={errors.origin.error}
            errorMessage={errors.origin.errorMessage}
            defaultValue={d2dData.origin.address}
            placeholder={FROM}
            img="/media/ic_origin.svg"
            onLocationSelect={(val) => handleValueChange(val, "origin")}
          />
          <div
            onClick={swapDestinations}
            className="bl-ts-btnswitch__h hidden lg:flex lg:mt-2"
          >
            <span></span>
          </div>
          <div
            onClick={swapDestinations}
            className="bl-ts-btnswitch__v lg:hidden h-14"
          >
            <span className="h-2-188"></span>
          </div>
        </div>
        <div className="col-span-12 mb-2 relative lg:mb-0 lg:col-span-1">
          <Location
            error={errors.destination.error}
            errorMessage={errors.destination.errorMessage}
            defaultValue={d2dData.destination.address}
            placeholder={TO}
            onLocationSelect={(val) => handleValueChange(val, "destination")}
          />
        </div>
        <div className="col-span-12 flex flex-col lg:pb-2 lg:mb-2 pt-1.5 lg:flex-row lg:gap-3 bl-ts-block__col lg:col-span-1">
          <div
            className={`lg:flex-grow  bl-ts-block__col mb-6 lg:mb-0 ${
              showDateRange && "bl-ts-selected"
            }`}
            onClick={() => {
              dateRangeToggle(!showDateRange);
            }}
          >
            <DateInput
              label={"Departure Date"}
              value={changeDateFormat(
                d2dData.date,
                DATE_FORMAT.YYYY_MM_DD,
                DATE_FORMAT.DAY_MM_DATE
              )}
            />
          </div>
        </div>
        <div className="col-span-12 flex flex-col lg:flex-row lg:gap-3 bl-ts-block__col lg:col-span-1">
          <TimePicker
            value={d2dData.time}
            onChangeHandler={(counter, value, timePeriod) =>
              handleTimeChange(counter, value, timePeriod, "time")
            }
            onTimeInputChange={handleTimeInputChange}
          />
        </div>
        <div className="col-span-12 my-6 lg:my-0 lg:flex-row lg:gap-3 bl-ts-block__col lg:col-span-1">
          <PassengerDropDown
            label={"Passengers"}
            onUpdate={handlePassengerCount}
            passengerOptions={Object.entries(d2dPassengers.passengers)}
            serviceOptions={Object.entries(d2dPassengers.serviceRequests)}
            classname="h-12 mt-1.5"
            selected={
              "" +
              parseInt(
                d2dData.adults_count +
                  d2dData.kids_count +
                  d2dData.infants_count
              )
            }
            totalCount={
              d2dData.adults_count + d2dData.kids_count + d2dData.infants_count
            }
          />
        </div>
        {isPlusDetailPage && <SearchBtn loading={loading} />}
      </div>
      {!isPlusDetailPage && <SearchBtn loading={loading} />}
      <DateComponent
        showDateRange={showDateRange}
        dateValue={dateValue}
        handleDateChange={handleDateChange}
        dateType={"single"}
        label={trainSearchWidget.searchType.label}
        dateRangeToggle={dateRangeToggle}
        classname={`${dateCompClass} ${isPlusDetailPage ? "top-36" : "top-28"}`}
        handleDateSelectionComplete={dateRangeToggle}
      />
    </>
  );
};

export default Door2DoorService;
0 Answers
Related