如何在打字稿中声明用于反应选择的道具?

时间:2020-10-01 03:55:45

标签: javascript reactjs typescript react-redux react-select

任何遇到过这种情况的人,我都不知道如何在Typescript中声明Select属性。请帮忙! enter image description here

import React from 'react'
import Select, {components, IndicatorProps} from 'react-select'
import {connect} from 'react-redux'
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import { Users } from '../../../Redux/Users/UsersReducer';
import { RootState } from '../../../Redux/rootReducer';

interface SelectButtonProps {
  onSelect: (event: React.FormEvent<HTMLSelectElement>) => void,
  users: Users[],
  stateId: string
}
const SelectUserButton:React.FunctionComponent<SelectButtonProps> = ({onSelect, users, stateId}): JSX.Element => {
    const options = users.map( (user:Users) => ({label: user.name, value:`${user.id}`}))

    const DropdownIndicator = (
        props : IndicatorProps<any>
      ) => {
        return (
          <components.DropdownIndicator {...props}>
            <ArrowDropDownIcon id="arrow_icon"/>
          </components.DropdownIndicator>
        );
      };
      const SingleValue = ({ children, ...props }:any) => (
        <components.SingleValue {...props}>
          {children}
        </components.SingleValue>
      );
    return (
        <div className='select__user'>
            <label htmlFor='react-select-container'>Users</label>
            <Select 
                SingleValue={SingleValue}
                name="user"
                components={{ DropdownIndicator }}
                options={options}
                onChange={onSelect}
                maxMenuHeight={120}
                placeholder={stateId}
            />
        </div>
    )
}

onChange事件发生错误,因为使用react-select时,它将返回一个对象。

And the browser also shows this error: "
The above error occurred in the <WithStyles(ForwardRef(SvgIcon))> component:
    in WithStyles(ForwardRef(SvgIcon))
    in ForwardRef
    in ForwardRef (at SelectUserButton.tsx:23)
    in div (created by Context.Consumer)
    in EmotionCssPropInternal (created by DropdownIndicator)
    in DropdownIndicator (at SelectUserButton.tsx:22)"

1 个答案:

答案 0 :(得分:0)

让我们从与SingleValue有关的简单错误/问题开始。

您的const SingleValue正在通过它收到的所有道具,因此它什么也不做。您可以编写const SingleValue = components.SingleValue,这将是同一回事。您也可以直接传递components.SingleValue,而无需将其分配给局部变量。

我看过“ react-select”的文档和源代码,虽然SingleValue似乎不是Select的道具,但奇怪的是这不会触发打字稿错误。相反,它应该是componentsDropdownIndicator旁边的一个附加属性。应该是components={{ DropdownIndicator, SingleValue: components.SingleValue }},但是由于您没有更改默认设置,因此根本不需要包含SingleValue

现在最困难的部分是事件处理。

您的接口声明onSelect属性是一个接收React.FormEvent<HTMLSelectElement>类型的事件的函数。不幸的是,由于“ react-select”包不会将实际事件传递给回调函数,因此无法正确调用此函数。

如果您要继续使用此软件包,则需要将SelectButtonProps界面更改为与您从“反应选择” onChange函数取回的数据兼容的界面。例如,它可以是一个接收所选Users对象的函数:

interface SelectButtonProps {
  onSelect: (user: Users) => void;
  users: Users[];
  stateId: string;
}

赋予onChange的第一个参数的打字稿类型为any,但实际上,它是选项数组中每个选项的类型为{label: string, value: (the type of your user.id which I don't know if it's string or number) }。坦白说,软件包作者可能在那里做得更好,因为他们确实应该根据您提供的options数组为您提供正确的类型。他们应该在多个地方使用泛型(值类型,选项类型),而使用诸如any之类的模糊类型。

这是可以传递给onChange的函数:

  const handleChange = (option: OptionTypeBase, meta: ActionMeta<any>): void => {
    console.log({ option, meta });
    onSelect({
      name: option.label,
      id: option.value
    });
  };

这不是必需的,但是另一种解决方法是,不要将用户映射到{label, value},然后再将{label, value}选项映射回到{ {1}}回调,您可以做的是直接将users数组传递给Select as User。然后,您可以使用自己的映射onChange和{来代替optionsgetOptionLabel)和option => option.labelgetOptionValue)的默认行为。 {1}}。

Revised Code