简体   繁体   中英

react-select and typescript: Type 'string' is not assignable to type 'ValueType<OptionTypeBase>'

I am trying to create an example component that uses react-select with typescript.

For this, I created a functional component and added the default example from react-select docs :

const options = [
    {value: 'chocolate', label: 'Chocolate'},
    {value: 'strawberry', label: 'Strawberry'},
    {value: 'vanilla', label: 'Vanilla'},
];

const MyComponent = () => {

    const [selectedOption, setSelectedOption] = useState('chocolate');

    const handleChange = (option: string) => {
        setSelectedOption(option);
    };

    return (
        <Select
            value={selectedOption}
            onChange={(option) => handleChange(option)}
            options={options}
        />
    );

};

However, this gives me an error:

 Overload 1 of 2, '(props: Readonly<Pick<Props<OptionTypeBase>, string | number> & Props<OptionTypeBase> & Props<OptionTypeBase>>): StateManager<...>', gave the following error.
    Type 'string' is not assignable to type 'ValueType<OptionTypeBase>'.
  Overload 2 of 2, '(props: Pick<Props<OptionTypeBase>, string | number> & Props<OptionTypeBase> & Props<OptionTypeBase>, context?: any): StateManager<...>', gave the following error.
    Type 'string' is not assignable to type 'ValueType<OptionTypeBase>'.

what am I doing wrong?

My packages are:

    "@types/react": "^16.9.19",
    "@types/react-dom": "^16.9.5",
    "@types/react-select": "^3.0.10",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-select": "^3.0.8",
    "typescript": "^3.7.5"

You need to set a value from your options array as the current value of Select component.

This however is not the only problem because the type signature of the onChange function is somewhat confusing. You'll need to define a type for the options and use `ValueType´ in the onChange function signature.

Here's a working example

type OptionType = {
  value: string;
  label: string;
};

const options: OptionType[] = [
  { value: "chocolate", label: "Chocolate" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" }
];

const MyComponent = () => {
  const [selectedOption, setSelectedOption] = useState<ValueType<OptionType>>(options[0]);

  const handleChange = (option: ValueType<OptionType>) => {
    setSelectedOption(option);
  };

  return (
    <Select
      value={selectedOption}
      onChange={option => handleChange(option)}
      options={options}
    />
  );
};

More information about the issue https://github.com/JedWatson/react-select/issues/2902

Sandbox with the code above https://codesandbox.io/s/angry-frost-5bh1o

  <Select
    value={selectedOption}
    onChange={(option) => handleChange(option)}
    options={options}
  />

The issue is value must be an entry within options . You have set the state to the string "chocolate" and it's throwing an error indicating that isn't of the same type.

If you update your state to something like:

  const [selectedOption, setSelectedOption] = useState(options[0]);

It'll now work.

import AsyncSelect from 'react-select/async';  

interface ColourOption {
    readonly value: string;
    readonly label: string;
    readonly color: string;
    readonly isFixed?: boolean;
    readonly isDisabled?: boolean;
  }
  
  const colourOptions: readonly ColourOption[] = [
    { value: 'ocean', label: 'Ocean', color: '#00B8D9', isFixed: true },
    { value: 'blue', label: 'Blue', color: '#0052CC', isDisabled: true },
    { value: 'purple', label: 'Purple', color: '#5243AA' },
    { value: 'red', label: 'Red', color: '#FF5630', isFixed: true },
    { value: 'orange', label: 'Orange', color: '#FF8B00' }
  ];
  

  const filterColors = (inputValue: string) => {
    return colourOptions.filter((i) =>
      i.label.toLowerCase().includes(inputValue.toLowerCase())
    );
  };
  
  const promiseOptions = (inputValue: string) =>
    new Promise<ColourOption[]>((resolve) => {
      setTimeout(() => {
        resolve(filterColors(inputValue));
      }, 1000);
    });    


<AsyncSelect 
    isMulti
    cacheOptions
    defaultOptions
    placeholder ={"Start typing to add another conditions"}
    loadOptions={promiseOptions}
    />

Try to do something like this:

type TSelectOption = {
    value: string;
    label: string;
};

const options: TSelectOption[] = [
    {value: 'chocolate', label: 'Chocolate'},
    {value: 'strawberry', label: 'Strawberry'},
    {value: 'vanilla', label: 'Vanilla'},
];

const MyComponent = () => {

const [selectedOption, setSelectedOption] = useState<Pick<TSelectOption, 'value'>>('chocolate');

const handleChange = (option: SingleValue<Pick<TSelectOption, 'value'>>) => {
    setSelectedOption(option);
};

   return (
       <Select
           value={selectedOption}
           onChange={(option) => handleChange(option)}
           options={options}
      />
   );

};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM