So this code is working, but sometimes on page load or refresh the google places dropdown autocomplete suggestions is not showing up, I can type anything in the searchbox but it just doesn't load the autocomplete box. What could cause this issue?
This is the code.
const apiKey = process.env.REACT_APP_GOOGLE_KEY;
const mapApiJs = 'https://maps.googleapis.com/maps/api/js';
const geocodeJson = 'https://maps.googleapis.com/maps/api/geocode/json';
// load google map api js
function loadAsyncScript(src) {
  return new Promise(resolve => {
    const script = document.createElement("script");
    Object.assign(script, {
      type: "text/javascript",
      async: true,
      src
    })
    script.addEventListener("load", () => resolve(script));
    document.head.appendChild(script);
  })
}
const extractAddress = (place) => {
  const address = {
    city: "",
    state: "",
    zip: "",
    country: "",
    plain() {
        const city = this.city ? this.city + ", " : "";
        const zip = this.zip ? this.zip + ", " : "";
        const state = this.state ? this.state + ", " : "";
        return city + zip + state + this.country;
    }
  }
  if (!Array.isArray(place?.address_components)) {
    return address;
  }
  if(typeof place.geometry.location.lat === 'function') {
    address.lat = place.geometry.location.lat();
  } else {
    address.lat = place.geometry.location.lat;
  }
  if(typeof place.geometry.location.lng === 'function') {
    address.lng = place.geometry.location.lng();
  } else {
    address.lng = place.geometry.location.lng;
  }
  place.address_components.forEach(component => {
    const types = component.types;
    const value = component.long_name;
    if (types.includes("locality")) {
      address.city = value;
    }
    if (types.includes("administrative_area_level_2")) {
      address.state = value;
    }
    if (types.includes("postal_code")) {
      address.zip = value;
    }
    if (types.includes("country")) {
      address.country = value;
    }
  });
  return address;
}
function ReportForm() {
    const searchInput = useRef(null);
    const [address, setAddress] = useState({});
    const [coords, setCoords] = useState({
        lat: 42.680115925419294,
        lng: 14.010667884881462,
    });
    // init gmap script
    const initMapScript = () => {
        // if script already loaded
        if(window.google) {
          return Promise.resolve();
        }
        const src = `${mapApiJs}?key=${apiKey}&libraries=places&v=weekly`;
        return loadAsyncScript(src);
    }
    // do something on address change
    const onChangeAddress = (autocomplete) => {
        const place = autocomplete.getPlace();
        setAddress(extractAddress(place));
        setCoords({
            lat: place.geometry.location.lat(),
            lng: place.geometry.location.lng(),
        });
    }
    // init autocomplete
    const initAutocomplete = () => {
        if (!searchInput.current) return;
        const autocomplete = new window.google.maps.places.Autocomplete(searchInput.current);
        autocomplete.setFields(["address_component", "geometry"]);
        autocomplete.addListener("place_changed", () => onChangeAddress(autocomplete));
    }
    const reverseGeocode = ({ latitude: lat, longitude: lng}) => {
        const url = `${geocodeJson}?key=${apiKey}&latlng=${lat},${lng}`;
        searchInput.current.value = "Getting your location...";
        fetch(url)
            .then(response => response.json())
            .then(location => {
              const place = location.results[0];
              const _address = extractAddress(place);
              setAddress(_address);
              searchInput.current.value = _address.plain();
              setCoords({
                lat: lat,
                lng: lng,
              });
            })
    }
    const findMyLocation = () => {
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(position => {
            reverseGeocode(position.coords)
          })
        }
    }
    // load map script after mounted
    useEffect(() => {
        initMapScript().then(() => initAutocomplete())
    }, []); 
    return(
        <>        
            <form>                    
                <div>
                    <div className="search">
                        <span><Search /></span>
                        <input 
                            name="address" 
                            ref={searchInput} 
                            type="text" 
                            placeholder="Search Address...." 
                        />
                        <button type="button" onClick={findMyLocation}><GpsFixed /></button>
                    </div>
                </div>                      
            </form>                       
        </>
    );
}
I have also tried with Material UI TextField and inputRef instead of the standard input, but I get the same problem. Also, it happens more often on page refresh. On first page load it almost works every time.
                        
Have you tried adding
searchInput.currentto the dependency array ofuseEffect? You have this lineif (!searchInput.current) return;insideinitAutocompleteand yoursearchInputis initially set tonull. So on page refresh it's possible there is a race condition between therefbeing set on the input element and the running of theinitAutocompletefunction.