web-dev-qa-db-ja.com

データが利用可能な場合、マテリアルUIコンポーネントはオートコンプリートしません

コンポーネントに自動提案を表示できません。コンソールでデータが使用可能であることが確認され、Material UI AutoCompleteコンポーネント機能を使用して提案プロップを使用してこのコンポーネントに送信しました here オプションを設定しようとしていますが、これらは次のように変更されます親コンポーネントで処理されるとおりに入力しましたが、値を設定しても反映されず、提案も表示されません。私は非常に混乱しています。私のコードは以下です。

import React, { FunctionComponent, FormEvent, ChangeEvent } from "react";
import { Grid, TextField, Typography } from "@material-ui/core";
import { CreateProjectModel, JobModel } from "~/Models/Projects";
import ErrorModel from "~/Models/ErrorModel";
import Autocomplete from "@material-ui/lab/Autocomplete";

type CreateProjectFormProps = {
    model: CreateProjectModel;
    errors: ErrorModel<CreateProjectModel>;
    onChange: (changes: Partial<CreateProjectModel>) => void;
    onSubmit?: () => Promise<void>;
    suggestions: JobModel[];
};

const CreateProjectForm: FunctionComponent<CreateProjectFormProps> = ({
    model,
    errors,
    onChange,
    onSubmit,
    suggestions,
}) => {
    const [open, setOpen] = React.useState(false);
    const [options, setOptions] = React.useState<JobModel[]>([]);
    const loading = open && options.length === 0;
    const [inputValue, setInputValue] = React.useState('');
    React.useEffect(() => {
        let active = true;

        if (!loading) {
            return undefined;
        }

        (async () => {
            if (active) {
                setOptions(suggestions);
            }
        })();

        return () => {
            active = false;
        };
    }, [loading]);

    React.useEffect(() => {
        if (!open) {
            setOptions([]);
        }
    }, [open]);

    const submit = async (event: FormEvent) => {
        event.preventDefault();
        event.stopPropagation();

        await onSubmit();
    };

    const change = (name: string) => (event: ChangeEvent<HTMLInputElement>) => {
        setInputValue(event.target.value);

        onChange({
            [name]: event.target.value,
        });
    };

    const getFieldProps = (id: string, label: string) => {
        return {
            id,
            label,
            helperText: errors[id],
            error: Boolean(errors[id]),
            value: model[id],
            onChange: change(id),
        };
    };

    return (
        <Autocomplete
            {...getFieldProps}
            open={open}
            onOpen={() => {
                setOpen(true);
            }}
            onClose={() => {
                setOpen(false);
            }}
            getOptionSelected={(option, value) => option.id === value.id}
            getOptionLabel={(option) => option.id}
            options={options}
            loading={loading}
            autoComplete
            includeInputInList            
            renderInput={(params) => (
                <TextField
                    {...getFieldProps("jobNumber", "Job number")}
                    required
                    fullWidth
                    autoFocus
                    margin="normal"
                />
            )}
            renderOption={(option) => {        
                return (
                  <Grid container alignItems="center">

                    <Grid item xs>
                      {options.map((part, index) => (
                        <span key={index}>
                          {part.id}
                        </span>
                      ))}
                      <Typography variant="body2" color="textSecondary">
                        {option.name}
                      </Typography>
                    </Grid>
                  </Grid>
                );
              }}            
        />
    );
};

export default CreateProjectForm;

提案の私のデータの例は次のようになります:

[{"id":"BR00001","name":"Aircrew - Standby at home base"},{"id":"BR00695","name":"National Waste"},{"id":"BR00777B","name":"Airly Monitor Site 2018"},{"id":"BR00852A","name":"Cracow Mine"},{"id":"BR00972","name":"Toowoomba Updated"},{"id":"BR01023A","name":"TMRGT Mackay Bee Creek"},{"id":"BR01081","name":"Newman Pilot Job (WA)"},{"id":"BR01147","name":"Lake Vermont Monthly 2019"},{"id":"BR01158","name":"Callide Mine Monthly Survey 2019"},{"id":"BR01182","name":"Lake Vermont Quarterly 2019 April"}]
6
Dean

私はあなたのコードにいくつかの問題に気づきました、getFieldPropsはページがロードされない原因となるIDまたは名前のパラメーターなしで呼び出されています。さらに重要なことに、propsを渡して使用するときは autocomplete docs に従うことを検討する必要があります。例えば:

renderInput={(params) => <TextField {...params} label="Controllable" variant="outlined" />}

私はいくつかの質問をしました、あなたがそれらの答えをいつ得ることができるか私に知らせますので、私は考えられるすべての問題に対処することができます。

Q1。ユーザー入力は、提案のnameプロパティから関連する一致を提供する必要がありますか、それともidのみですか?例として。 「レイク」と入力した場合、マッチとしてBRO1182、レイクバーモントクォータリー2019エイプリルを表示しますか?

Q2。エラーケースにどのように対処しましたか?エラーモデルがあるようですが、エラーが発生したときにそれを使用してオートコンプリートのスタイルを設定する方法がわかりません

Q3。送信ボタンがありませんか? onSubmit関数が表示されますが、コードでは使用されていません。

Q4。オープン状態とロード状態が必要な特別な理由はありますか?

以下は、ユーザー入力から関連する一致を表示するためにこれまでに試みたものです

import React, { FunctionComponent, FormEvent, ChangeEvent } from "react";
import { Grid, TextField, Typography } from "@material-ui/core";
import { CreateProjectModel, JobModel } from "~/Models/Projects";
import ErrorModel from "~/Models/ErrorModel";
import Autocomplete from "@material-ui/lab/Autocomplete";

type CreateProjectFormProps = {
  model: CreateProjectModel;
  errors: ErrorModel<CreateProjectModel>;
  onChange: (changes: Partial<CreateProjectModel>) => void;
  onSubmit?: () => Promise<void>;
  suggestions: JobModel[];
};

const CreateProjectForm: FunctionComponent<CreateProjectFormProps> = ({
  model,
  errors,
  // mock function for testing
  // consider a better name like selectChangeHandler
  onChange = val => console.log(val),
  // consider a better name like submitJobFormHandler
  onSubmit,
  suggestions: options = [
    { id: "BR00001", name: "Aircrew - Standby at home base" },
    { id: "BR00695", name: "National Waste" },
    { id: "BR00777B", name: "Airly Monitor Site 2018" },
    { id: "BR00852A", name: "Cracow Mine" },
    { id: "BR00972", name: "Toowoomba Updated" },
    { id: "BR01023A", name: "TMRGT Mackay Bee Creek" },
    { id: "BR01081", name: "Newman Pilot Job (WA)" },
    { id: "BR01147", name: "Lake Vermont Monthly 2019" },
    { id: "BR01158", name: "Callide Mine Monthly Survey 2019" },
    { id: "BR01182", name: "Lake Vermont Quarterly 2019 April" }
  ]
}) => {
  const [value, setValue] = React.useState<JobModel>({});
  const loading = open && options.length === 0;

  // this pc of code is not used, why?
  const submit = async (event: FormEvent) => {
    event.preventDefault();
    event.stopPropagation();

    await onSubmit();
  };

  const handleChange = (_: any, value: JobModel | null) => {
    setValue(value);

    onChange({
      [value.name]: value.id
    });
  };

  // consider passing in props instead
  const getFieldProps = (id: string, label: string) => {
    return {
      id,
      label,
      // not sure what this is
      helperText: errors[id],
      // not sure what this is
      error: Boolean(errors[id]),
      value: model[id],
      onChange: change(id)
    };
  };

  return (
    <Autocomplete
      id="placeholder-autocomplete-input-id"
      // for selection, use value see docs for more detail
      value={value}
      onChange={handleChange}
      getOptionSelected={(option, value) => option.id === value.id}
      getOptionLabel={option => option.id}
      options={options}
      loading={loading}
      autoComplete
      includeInputInList
      renderInput={params => (
        // spreading the params here will transfer native input attributes from autocomplete
        <TextField
          {...params}
          label="placeholder"
          required
          fullWidth
          autoFocus
          margin="normal"
        />
      )}
      renderOption={option => (
        <Grid container alignItems="center">
          <Grid item xs>
            <span key={option}>{option.id}</span>
            <Typography variant="body2" color="textSecondary">
              {option.name}
            </Typography>
          </Grid>
        </Grid>
      )}
    />
  );
};

export default CreateProjectForm;

下のボタンをクリックすると、私のコードサンドボックスで実行されているコードを確認できます

Edit sharp-newton-87eng

1
user3366943

私があなたのコードを理解して正しく発行した場合、あなたは欲しい-


    React.useEffect(() => {
      let active = true;

      if (!loading) {
        return undefined;
      }

      (async () => {
         if (active) {
             setOptions(suggestions);
          }
       })(); 

      return () => {
         active = false;
      };
   }, [loading]);

毎回実行してoptionsを更新しますが、[loading]依存関係は次のように設定されています


     const loading = open && suggestions.length === 0;

変更をトリガーしません。

そうすることを検討してください-


 const loading = useLoading({open, suggestions})


 const useLoading = ({open, suggestions}) => open && suggestions.length === 0;
0
Hagai Harari