Material UI自动完成上的打字稿平等问题 [英] Typescript Equality issue on Material UI Autocomplete

查看:139
本文介绍了Material UI自动完成上的打字稿平等问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

数据存储为:

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

传递给自动完成的值是:

Value passed to the Autocomplete is:

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

控制台中报告了错误

Material-UI:提供给自动完成"的值无效. 没有任何选项与{"label":"United Kingdom","iso":"gb","country":"United Kingdom"}匹配.

Material-UI: the value provided to Autocomplete is invalid. None of the options match with {"label":"United Kingdom","iso":"gb","country":"United Kingdom"}.

value={}

键入字符串|无法将"ICountry"分配给"ICountry | ICountry"类型ICountry [] |空|不明确的'. 类型'string'不能分配给类型'ICountry | ICountry [] |空|未定义".

Type 'string | ICountry' is not assignable to type 'ICountry | ICountry[] | null | undefined'. Type 'string' is not assignable to type 'ICountry | ICountry[] | null | undefined'.

问题:将数据传递给组件并没有将其设置为相应的选项,我完全不知道如何解决此问题.

Issue: Passing in data to the component doesn't set it to the corresponding option, I'm all out of ideas on how to resolve this issue.

发行的Codesandbox: https://codesandbox.io/s/charming-firefly- zl3qd?file =/src/App.tsx

Codesandbox of issue: 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;

countries.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的完整消息是:

Material-UI:提供给自动完成"的值无效. 没有一个选项与{"label":"United Kingdom","iso":"gb","country":"United Kingdom"}匹配. 您可以使用getOptionSelected道具来自定义相等性测试.

Material-UI: the value provided to Autocomplete is invalid. None of the options match with {"label":"United Kingdom","iso":"gb","country":"United Kingdom"}. You can use the getOptionSelected prop to customize the equality test.

默认的相等性测试只是===,因此,如果您的选项是对象,则您的值必须是那些确切的对象之一才能匹配.具有相同值的其他对象将不匹配.

The default equality test is simply ===, so if your options are objects, your value would have to be one of those exact objects in order to match. A different object with the same values will not match.

但是正如消息告诉您的那样,您可以通过getOptionSelected道具自定义相等性测试.例如,您可以指定:

But as the message tells you, you can customize the equality test via the getOptionSelected prop. For instance you could specify:

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

或者您可以对所有对象属性进行深度相等性检查.

or you could do a deep equality check of all the object properties.

可以使用value={values.address.country as ICountry}修复类型错误.

The type error can be fixed with value={values.address.country as ICountry}.

这是您的沙盒的工作版本: https://codesandbox.io/s/autocomplete -getoptionselected-b6n3s

Here is a working version of your sandbox: https://codesandbox.io/s/autocomplete-getoptionselected-b6n3s

这篇关于Material UI自动完成上的打字稿平等问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆