J. Jackson
J. Jackson

Reputation: 3774

Using "use-places-autocomplete" hook with Material-UI's Autocomplete?

I'm trying to use this hook along with Material-UI's Autocomplete component, but am not having much success. Does anyone have an example of this scenario?

I receive a TS error for the value prop, stating

Type 'string' is not assignable to type 'AutocompletePrediction | null | undefined'.

The main issue though is that when I type into the input, results aren't being displayed for some reason, and neither the handleSelect nor the handleInput methods are being triggered.

Here's what I have so far:

import { useEffect, useRef, useState } from 'react';
import {
  ClickAwayListener,
  Grid,
  TextField,
  Typography,
} from '@material-ui/core';
import LocationOnIcon from '@material-ui/icons/LocationOn';
import parse from 'autosuggest-highlight/parse';
import Autocomplete from '@material-ui/lab/Autocomplete';
import usePlacesAutocomplete, {
  getGeocode,
  getLatLng,
} from 'use-places-autocomplete';

interface Props {
  onSelect: (value: string) => void;
}

const EditLocation: React.FC<Props> = ({ onSelect }) => {
  const {
    ready,
    value,
    suggestions: { status, data },
    setValue,
    clearSuggestions,
  } = usePlacesAutocomplete({
    debounce: 300,
  });

  const handleInput = e => {
    setValue(e.target.value);
  };

  const handleSelect =
    ({ description }: { description: string }) =>
    () => {
      console.log({ description });
      // When user selects a place, we can replace the keyword without request data from API
      // by setting the second parameter to "false"
      setValue(description, false);
      clearSuggestions();

      // Get latitude and longitude via utility functions
      getGeocode({ address: description })
        .then(results => getLatLng(results[0]))
        .then(({ lat, lng }) => {
          console.log('📍 Coordinates: ', { lat, lng });
        })
        .catch(error => {
          console.log('😱 Error: ', error);
        });
    };

  return (
    <ClickAwayListener onClickAway={() => clearSuggestions()}>
      <Autocomplete
        style={{ width: 300 }}
        getOptionLabel={option =>
          typeof option === 'string' ? option : option.description
        }
        filterOptions={x => x}
        options={data}
        autoComplete
        includeInputInList
        filterSelectedOptions
        value={value} // <-- TS Error: "Type 'string' is not assignable to type 'AutocompletePrediction | null | undefined'."
        onChange={handleInput}
        renderInput={params => (
          <TextField
            {...params}
            size="small"
            label="Trip location"
            variant="outlined"
            fullWidth
          />
        )}
        renderOption={option => {
          const matches =
            option.structured_formatting.main_text_matched_substrings;
          const parts = parse(
            option.structured_formatting.main_text,
            matches.map(match => [match.offset, match.offset + match.length])
          );

          return (
            <Grid
              container
              alignItems="center"
              onClick={() => handleSelect(option)}>
              <Grid item>
                <LocationOnIcon />
              </Grid>
              <Grid item xs>
                {parts.map((part, index) => (
                  <span
                    key={index}
                    style={{ fontWeight: part.highlight ? 700 : 400 }}>
                    {part.text}
                  </span>
                ))}

                <Typography variant="body2" color="textSecondary">
                  {option.structured_formatting.secondary_text}
                </Typography>
              </Grid>
            </Grid>
          );
        }}
      />
    </ClickAwayListener>
  );
};

export default EditLocation;

Upvotes: 2

Views: 1517

Answers (1)

NearHuscarl
NearHuscarl

Reputation: 81500

The value property returned by usePlacesAutocomplete has type string while the data has type Suggestion[]. In order to make the Autocomplete stop complaining about the error, you need to pass a value with Suggestion type to the value prop of Autocomplete:

Autocomplete prop types: 1, 2.

<Autocomplete
  options={data}
  value={data.find(x => x.description === value)}

Upvotes: 1

Related Questions