web-dev-qa-db-ja.com

FormikでMaterial-UI Autocompleteコンポーネントを使用する

現在、FormikでMaterial UIの Autocomplete コンポーネントを使用しようとしています。これまでのところ、テキストフィールドやMaterial-UIからの従来の選択などは、Formikで非常にうまく機能します。オートコンプリートの実装はそうではありません。 FormikのonChangeハンドラーがcity_idの値を更新していないようです。私はオートコンプリートがまだMaterial-UIのコアライブラリの一部ではないことを知っていますが、現時点でこのようなことが可能であるかどうかを確認していました。

import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form } from 'formik';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';

import { cities } from '../data/cities';

import "./styles.css";

const initialValues = {
  city_id: '',
};

const submit = params => {
  alert(`Value for city_id is: ${params.city_id}`);
};

function App() {
  return (
     <Formik
      initialValues={ initialValues }
      onSubmit={ submit }
    >
      {({
        handleChange,
        values,
      }) => (
        <Form>
          <Autocomplete
            id="city_id"
            name="city_id"
            options={ cities }
            groupBy={ option => option.state }
            getOptionLabel={ option => option.name }
            style={{ width: 300 }}
            renderInput={params => (
              <TextField
                { ...params }
                onChange={ handleChange }
                margin="normal"
                label="Cities"
                fullWidth
                value={ values.city_id }
              />
            )}
          />

          <Button
            variant="contained"
            color="primary"
            type="submit"
          >
            Submit
          </Button>
        </Form>
      )}
    </Formik>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit angry-goldstine-8offj

3
Carl Edwards

あなたの問題は、handleChangeがあなたがしているように機能しないことです。

handleChange docs を見てみると:

一般的な入力変更イベントハンドラ。これにより、values [key]が更新されます。ここで、keyはイベントを発行する入力の名前属性です。 name属性が存在しない場合、handleChangeは入力のid属性を探します。注:ここでの「入力」とは、すべてのHTML入力を意味します。

正常に動作するはずですが、問題は、TextField内のAutocompleteが何かを入力したときにのみhandleChangeをトリガーし、値はテキストであり、 idまたはその他の必要なプロパティなので、handleChangeAutocompleteに移動する必要があります。

そして、もう1つの問題があります。handleChangeAutocompleteを使用することはできません。これは、必要な入力を参照せず、通常のonChangeとは異なるパラメーターも持っているためです。 docs で確認できるように、inputの.

onChange
機能
値が変更されたときに呼び出されるコールバック。
署名:
function(event: object, value: any) => void
event:コールバックのイベントソース
value:null

だからあなたがする必要があるのはsetFieldValueを使ってAutocompleteに渡すことです

onChange={(e, value) => setFieldValue("city_id", value)}

フィールドの名前と取得したい値を渡す必要があります。

これが 動作例 です

4
Vencovsky

@vencovskyが正解を提供してくれましたが、Material UI 14.10.1でまだ機能しています。

required検証を使用してフィールドをYupに設定しているので、もう少し追加しています。

これを正しく動作させるには、次のようにします。Yup config:

validationSchema = {
    Yup.object().shape({
        contact: Yup.string().max(255).required('Contact is required'),
    })
}

反応:

<Autocomplete
    id="contact-autocomplete"
    options={contacts}
    getOptionLabel={(contact) => `${contact?.firstName} ${contact?.lastName}`}
    onChange={(e, value) => setFieldValue("contact", value?.id || "")}
    onOpen={handleBlur}
    includeInputInList
    renderInput={(params) => (
        <TextField
            {...params}
            error={Boolean(touched.contact && errors.contact)}
            fullWidth
            helperText={touched.contact && errors.contact}
            label="Contact Person"
            name="contact"
            variant="outlined"
        />
    )}
/>

ユーザーがAutocomplete要素をクリックすると、onOpenを起動してFormikonBlurを実行し、フィールドにタッチ済みのマークを付けます。アイテムが選択されない場合、Formik flagsフィールドを表示してContact is required検証メッセージ。

1
richardw