reactjsmaterial-uimui-autocomplete

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


I'm trying to use this hook along with Material UI 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;

Solution

  • 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)}