programing

재료 UI 자동 완성의 유형 스크립트 동일 문제

sourcejob 2023. 6. 23. 22:02
반응형

재료 UI 자동 완성의 유형 스크립트 동일 문제

데이터는 다음과 같이 저장됩니다.

 { iso: "gb", label: "United Kingdom", country: "United Kingdom" },
 { iso: "fr", label: "France", country: "France" }

자동 완성으로 전달되는 값은 다음과 같습니다.

{ iso: "gb", label: "United Kingdom", country: "United Kingdom" }

콘솔에 오류가 보고됨

재료 UI: 자동 완성에 제공된 값이 잘못되었습니다.일치하는 옵션이 없습니다.{"label":"United Kingdom","iso":"gb","country":"United Kingdom"}.

보고된 유형 오류value={}

'string | Icountry' 유형은 '유형에 할당할 수 없습니다.I country | I country[] | null | 정의되지 않음'입니다.'string' 유형은 ' 유형에 할당할 수 없습니다.I country | I country[] | null | 정의되지 않음'입니다.

문제: 구성 요소에 데이터를 전달해도 해당 옵션으로 설정되지 않으므로 이 문제를 해결하는 방법에 대한 아이디어가 부족합니다.

문제의 코드 및 상자: https://codesandbox.io/s/charming-firefly-zl3qd?file=/src/App.tsx

import * as React from "react";
import { Box, Typography, TextField, Button } from "@material-ui/core";
import { Autocomplete } from "@material-ui/lab";
import "./styles.css";
import { countries } from "./countries";
import { investors } from "./investor";
import { Formik } from "formik";

interface ICountry {
  iso: string;
  country: string;
  label: string;
}

const isoToFlag = (isoCode: string) => {
  if (isoCode) {
    return typeof String.fromCodePoint !== "undefined"
      ? isoCode
          .toUpperCase()
          .replace(/./g, char =>
            String.fromCodePoint(char.charCodeAt(0) + 127397)
          )
      : isoCode;
  }
  return "";
};

const App: React.FC = () => {
  const investor = investors.find(element => element.id === "123");


  return (
    <div className="App">
      <Formik
        initialValues={{
          address: {
            country: investor?.legal.address.country ? investor.legal.address.country : '',
          }
        }}
        onSubmit={(values, actions) => {
          console.log({ values, actions });
          actions.setSubmitting(false);
        }}
      >
        {({ submitForm, isSubmitting, values, setFieldValue, setValues }) => {

          return (
            <form>

              <Autocomplete
                id="country"
                options={countries}
                getOptionLabel={option => option.label}
                value={values.address.country}
                renderOption={(option: ICountry) => (
                  <Box display="flex" flexDirection="row" alignItems="center">
                    <Box mr={1}>{isoToFlag(option.iso)}</Box>
                    <Box>
                      <Typography variant="body2">{option.label}</Typography>
                    </Box>
                  </Box>
                )}
                onChange={(e: object, value: any | null) => {
                  console.log('do the types match?', typeof value === typeof values.address.country);
                  console.log('do the objects match?', value === values.address.country);
                  console.log('the objects in question', value, values.address.country);
                  console.log("                  ");
                  setFieldValue("address.country", value);
                }}
                renderInput={params => (
                  <TextField
                    {...params}
                    name="address.country"
                    label="Country"
                    variant="outlined"
                    fullWidth
                  />
                )}
              />
              <Button
                variant="contained"
                size="large"
                color="primary"
                disabled={isSubmitting}
                onClick={submitForm}
              >
                Submit
              </Button>
            </form>
          );
        }}
      </Formik>
    </div>
  );
};

export default App;

국가들.ts


import { ICountry } from "./investor";

export const countries: ICountry[] = [
  {
    iso: "gb",
    label: "United Kingdom",
    country: "United Kingdom"
  },
  {
    iso: "fr",
    label: "France",
    country: "France"
  }
];

에서 온 전체 메시지Material-UI다음과 같습니다.

재료 UI: 자동 완성에 제공된 값이 잘못되었습니다.일치하는 옵션이 없습니다.{"label":"United Kingdom","iso":"gb","country":"United Kingdom"}사용할 수 있습니다.getOptionSelected동등성 검정을 사용자 정의하기 위한 prop.

기본 동일성 검정은 다음과 같습니다.===따라서 옵션이 개체인 경우 일치시키려면 값이 정확한 개체 중 하나여야 합니다.값이 같은 다른 개체는 일치하지 않습니다.

그러나 메시지에서 알 수 있듯이 다음을 통해 동등성 테스트를 사용자 정의할 수 있습니다.getOptionSelected예를 들어 다음을 지정할 수 있습니다.

getOptionSelected={(option, value) => option.iso === value.iso}

또는 모든 개체 속성에 대한 완전 동일성 검사를 수행할 수 있습니다.

형식 오류는 다음을 사용하여 수정할 수 있습니다.value={values.address.country as ICountry}.

다음은 v4를 사용하는 샌드박스의 작동 버전입니다. https://codesandbox.io/s/autocomplete-getoptionselected-b6n3s

다음은 v5에 필요한 수정 사항이 포함된 작동 버전입니다. https://codesandbox.io/s/autocomplete-getoptionselected-forked-rfz625?file=/src/App.tsx

v5 버전은 다음을 사용합니다.isOptionEqualToValue대신에getOptionSelected

                isOptionEqualToValue={(option, value) =>
                  option.iso === value.iso
                }

v5 버전은 또한 다음을 변경합니다.renderOption마이그레이션 안내서에 설명된 구문입니다.

Auto Complete 구성 요소의 getOptionSelected(Materail-UI - 4+ 지원) 속성을 isOptionEqualToValue(Materail-UI - 5+ 지원)로 변경했습니다.

오류:

<Autocomplete
    fullWidth={true}
    label={props.label}
    margin={'noraml'}
    multiple={false}
    name={props.name}
    getOptionSelected={useCallback((option, value) => option.value === value.value)} // Materail-UI - 4+ support
    value={props.value}
    options={dropDown[props.id] || props.options}
    ref={selectRef}
    onChange={useCallback((e, v) => {
        if (typeof v === 'object' && v !== null) {
            _onChange(e, v)
        } else {
            _onChange(e, {label: ''})
        }
    })}
/>

솔루션:

<Autocomplete
    fullWidth={true}
    label={props.label}
    margin={'noraml'}
    multiple={false}
    name={props.name}
    isOptionEqualToValue={useCallback((option, value) => option.value === value.value, [])} // Materail-UI - 5+ support
    value={props.value}
    options={props.options}
    ref={selectRef}
    id='disable-clearable'
    disableClearable
    renderInput={useCallback(params => (
        <TextField {...params} label='disableClearable' variant='standard' />
    ), [])}
    onChange={useCallback((e, v) => {
        if (typeof v === 'object' && v !== null) {
            _onChange(e, v)
        } else {
            _onChange(e, {label: ''})
        }
    }, [])}
/>

언급URL : https://stackoverflow.com/questions/61504777/typescript-equality-issue-on-material-ui-autocomplete

반응형