javascriptreactjsgoogle-mapsreact-google-maps

Cannot access this.searchBox from StandaloneSearchBox in react-google-maps/api


I am trying to access the getPlaces() function which should be in the StandaloneSearchBox component from react-google-maps/api. In the documentation and other examples the are using it this way:

function Map() {

 // does not work.
 // Error -> 'this' implicitly has type 'any' because it does not have a type 
 // annotation.ts(2683)
 // index.tsx(22, 10): An outer value of 'this' is shadowed by this container.
 const onPlacesChanged = () => console.log(this.searchBox.getPlaces());

  return (
    <LoadScript
      googleMapsApiKey="YOUR-API-KEY"
      libraries={places}
    >
      <GoogleMap
        mapContainerStyle={containerStyle}
        center={center}
        zoom={zoom}
      >
        { /* Child components, such as markers, info windows, etc. */}
        <>
          <StandaloneSearchBox onPlacesChanged={onPlacesChanged} >
            <input
              type='text'
              placeholder='Customized your placeholder'
              style={{
                boxSizing: 'border-box',
                border: `1px solid transparent`,
                width: `270px`,
                height: `40px`,
                padding: `0 12px`,
                borderRadius: `3px`,
                boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
                fontSize: `14px`,
                outline: `none`,
                margin: 'center',
                textOverflow: `ellipses`,
                position: 'absolute',
                top: '40px',
                marginLeft: '50%'
              }}
            />
          </StandaloneSearchBox>
        </>
      </GoogleMap>
    </LoadScript>
  )
}

I am trying it this way because it is the only way I manage to get this inside that function:

// ... all the same 

// does not work either, this is a strange object and "searchBox" does not exists in it
function onPlacesChanged(this: any) {
     console.log(this.searchBox.getPlaces())
  }

// ... all the same

But I have problem accessing the searchBox property from this. When I print this it shows a large strange object with properties like `{e3: {…}, gm_bindings: {…}, gm_accessors_: {…}}

Have someone faced this problem before?

In the documentation, the function onPlacesChanged is describe like this:

onPlacesChanged (() => void) | undefined 

Description:    This event is fired when the user selects a query, getPlaces should be used to get new places.

Solution

  • Here are the suggestions on how to make your code work:

    1. I can see that you are using functional component in your code. You can't use this in functional component. You can use the useState instead. Instead of this.searchBox, you can use const [searchBox, setSearchBox] = useState(null);

    2. Once you have the useState, use the onLoad props of your SearchBox to call a function where you put the ref of your Searchbox object to the searchbox state.

    3. In your onPlacesChanged, you can just log the searchBox.getPlaces() to get the result of your getPlaces.

    Here's the working code and the code snippet:

    /*global google*/
    import ReactDOM from 'react-dom';
    import React, { useState } from 'react';
    
    import {
      GoogleMap,
      StandaloneSearchBox,
      LoadScript
    } from '@react-google-maps/api';
    const lib = ['places'];
    const center = { lat: 40.756795, lng: -73.954298 };
    function Map() {
      const [searchBox, setSearchBox] = useState(null);
    
      const onPlacesChanged = () => console.log(searchBox.getPlaces());
      const onSBLoad = ref => {
        setSearchBox(ref);
      };
    
      return (
        <LoadScript
          googleMapsApiKey="YOUR_KEY"
          libraries={lib}
        >
          <GoogleMap
            mapContainerStyle={{ height: '400px', width: '800px' }}
            center={center}
            zoom={12}
          >
            {/* Child components, such as markers, info windows, etc. */}
            <>
              <StandaloneSearchBox
                onPlacesChanged={onPlacesChanged}
                onLoad={onSBLoad}
              >
                <input
                  type="text"
                  placeholder="Customized your placeholder"
                  style={{
                    boxSizing: 'border-box',
                    border: `1px solid transparent`,
                    width: `270px`,
                    height: `40px`,
                    padding: `0 12px`,
                    borderRadius: `3px`,
                    boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
                    fontSize: `14px`,
                    outline: `none`,
                    margin: 'center',
                    textOverflow: `ellipses`,
                    position: 'absolute',
                    top: '40px',
                    marginLeft: '50%'
                  }}
                />
              </StandaloneSearchBox>
            </>
          </GoogleMap>
        </LoadScript>
      );
    }
    export default Map;