1. ホーム
  2. javascript

[解決済み] マテリアルUIを用いたReactのオートコンプリート

2022-03-07 20:34:12

質問

Material UIライブラリを使用して、オートコンプリートのコンポーネントを実装しています。

しかし、問題があります。TextFieldのカスタム実装でvalueとonChangeも必要なので、valueとonChangeを適切に渡す方法がよくわかりません。AutocompleteとTextFieldに2回valueとonChangeを渡すべきでしょうか?それとも、もっと良い解決策があるのでしょうか?ご教示いただければ幸いです。 以下は私のコードです。

import { Autocomplete as MuiAutocomplete } from '@material-ui/lab'
import { FormControl } from 'components/_helpers/FormControl'
import { useStyles } from 'components/Select/styles'
import { Props as TextFieldProps, TextField } from 'components/TextField'

export type Props = Omit<TextFieldProps, 'children'> & {
  options: Array<any>
  value: string
  onChange: (value: string) => void

  disabled?: boolean
}

export const Autocomplete = (props: Props) => {
  const classes = useStyles()

  return (
    <FormControl
      label={props.label}
      error={props.error}
      helperText={props.helperText}
    >
      <MuiAutocomplete
        options={props.options}
        // value={props.value}
        // onChange={event =>
        //   props.onChange((event.target as HTMLInputElement).value as string)
        // }
        classes={{
          option: classes.menuItem,
        }}
        disabled={props.disabled}
        getOptionLabel={option => option.label}
        renderInput={params => (
          <TextField
            {...params}
            placeholder={props.placeholder}
            value={props.value}
            onChange={props.onChange}
          />
        )}
        renderOption={option => {
          return <Typography>{option.label}</Typography>
        }}
      />
    </FormControl>
  )
}```

解決方法は?

Material UI には、オートコンプリート vs 入力値の状態を処理するためのプロップスが組み込まれています。

こちらのドキュメントで使用されている様子を見ることができます。 https://material-ui.com/components/autocomplete/#controllable-states

この例では、次のように inputChangeonInputChange プロパティを Autocomplete コンポーネントに追加します。これらのパラメータは renderInput 関数を使用します。

つまり、最終的なコードは、リンク先のドキュメントからコピーした以下のスニペットのようなものになります。

<Autocomplete
  value={value}
  onChange={(event, newValue) => {
    setValue(newValue);
  }}
  inputValue={inputValue}
  onInputChange={(event, newInputValue) => {
    setInputValue(newInputValue);
  }}
  id="controllable-states-demo"
  options={options}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="Controllable" variant="outlined" />}
/>