3

I have a react component for a google.maps.places.SearchBox without the map, which is a StandaloneSearchBox. I want to pass it props with the initial value (which is only the formated version of the address, e.g "London, Kentucky, États-Unis") and then be able to change the address in the input field.

I have a places property in the state, which I want to hold the place object. How can I pass in the beginning in the componentDidMount() method the initial value so I can set it to the places object? It doesn't work in this way.

const PlacesWithStandaloneSearchBox = compose(
withProps({
    googleMapURL: googleMapsURI,
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div style={{ height: `400px` }} />
}),
lifecycle({
    componentWillMount() {
        console.log("componentWillMount");
        const refs = {};

        this.setState({
            places: [],
            onSearchBoxMounted: ref => {
                refs.searchBox = ref;
            },
            onPlacesChanged: () => {
                const places = refs.searchBox.getPlaces();

                this.setState({
                    places
                });

            }
        })
    },
    componentDidMount() {
        this.setState({
            places: this.props.value
        });
    }
}),
withScriptjs
)(props =>
<div className="fretlink-input form-group" data-standalone-searchbox="">
    <StandaloneSearchBox
        ref={ props.onSearchBoxMounted }
        bounds={ props.bounds }
        onPlacesChanged={ props.onPlacesChanged }>
        <input
            className="form-control"
            placeholder={ props.placeholder }
            type="text" />
    </StandaloneSearchBox>
    <ol>
        { props.places.map(({ place_id, formatted_address, geometry: { location } }) =>
            <li key={ place_id }>
                { formatted_address }
                {" at "}
                ({location.lat()}, {location.lng()})
            </li>
        )}
    </ol>
</div>
);

export default PlacesWithStandaloneSearchBox;
davnicwil
  • 28,487
  • 16
  • 107
  • 123
ikken32
  • 103
  • 9

2 Answers2

1

It appears that initializing the StandaloneSearchBox with an actual Google Maps place object, based on a search on address text or lat lng, isn't possible out of the box with a component prop or otherwise.

I think the best you can do is implement this yourself, by manually doing a search with the Google Maps places API with whatever data you have, getting that initial place, and setting it via this.setState in componentDidMount as in your example.

However, I didn't do this, because I found a solution to this that's a lot simpler, and I think will also apply in your case.

If you have the formatted address, there may actually be no reason to perform the search and populate the component with a full Google Maps place at all. All you really need is that text showing in the input. When you search for a new address, sure, you need all the data (lat lng etc) -- but that is already working. For the initial address, you probably already have this data. It's really just what you show in the <input> that's your concern.

Fortunately, it's really easy to separate the behaviour of the <input> from the behaviour of the StandaloneSearchBox because the <input> is just a child component that you can fully control.

What I did was just to use some more component state to hold the text that the input should show, and then make it a controlled component. Everything else works in exactly the same way, it's just that I take control of the 'view' which is the text displayed in the <input>.

Here is a rough example of what I mean, using your code:

  // init the state with your initial value "1 Something Street, etc"
  const [text, setText] = useState(INITIAL_VALUE_HERE)

  <StandaloneSearchBox
    ref={ props.onSearchBoxMounted }
    bounds={ props.bounds }
    // have onPlacesChanged set the state when a new option is picked
    // to whatever the address text of the selected place is
    // (needs to be implemented appropriately in onPlacesChanged of course)
    onPlacesChanged={() => { props.onPlacesChanged(setText) }}
  >
    <input
      className="form-control"
      placeholder={ props.placeholder }
      type="text"
      value={text} // control the input value with state
      onChange={(e) => { setText(e.target.value) }} // update the state when you type something
    />
  </StandaloneSearchBox>
davnicwil
  • 28,487
  • 16
  • 107
  • 123
  • I tried this but when the component is presented an initial search isn't performed. No places are fetched. How do you get to search for results using INITIAL_VALUE_HERE as soon the component renders? – Douglas Mendes Oct 11 '22 at 11:13
  • @DouglasMendes this was a while ago, but rereading my answer here I think I was saying you can't do this. Or at least you couldn't at the time of writing -- perhaps the component has changed since :-) – davnicwil Oct 11 '22 at 11:49
  • I ended up faking it by calling `new window.google.maps.places.PlacesService(map).findPlaceFromQuery` myself and called the same onPlacesChanged with the result. Also in the StandaloneSearchBox in order to use a state for the value AND stick to the behavior where the chosen location from the drop down (suggestions) becomes the value for the input, I had to set such state when onPlacesChanged is fired by this very component. – Douglas Mendes Oct 19 '22 at 12:47
0

You can check my answer here: Initialize React Google Maps StandaloneSearchBox with geocode

In general you can't use address as a filter for SearchBox results, but you can specify the area in which to search for places:

<StandaloneSearchBox
  ref={props.onSearchBoxMounted}
  bounds={props.bounds}
  onPlacesChanged={props.onPlacesChanged}
  defaultBounds={new google.maps.LatLngBounds(
        new google.maps.LatLng(40.712216, -74.22655),
        new google.maps.LatLng(40.773941, -74.12544)
  )}
Alex
  • 1,986
  • 22
  • 23