将 Typescript 类型添加到 react-select onChange 函数 [英] Add Typescript types to react-select onChange function

查看:100
本文介绍了将 Typescript 类型添加到 react-select onChange 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在我的应用程序中使用来自 React Select 的 CreatableSelect 组件但我在添加 Typescript 类型时遇到问题.

I am using the CreatableSelect component from React Select in my application but I am having trouble adding Typescript types.

我想要做的就是使用正确的类型从 handleChange = (value: any) 更改 any .我使用了这个 const handleChange = (value: { label: any; value: any }[]) =>{ 但它不起作用.

All I want to do is to change any from handleChange = (value: any) with the right types. I used this const handleChange = (value: { label: any; value: any }[]) => { but it does not work.

如何将 any 类型更改为正确的类型?

How can I change any type to the right type?

演示:https://codesandbox.io/s/codesandboxer-example-forked-9tsfp?file=/example.js

export default class CreatableInputOnly extends Component<*, State> {
  state = {
    inputValue: "",
    value: []
  };
  handleChange = (value: any) => {
    console.log(value, "test");
    this.setState({ value });
  };
  handleInputChange = (inputValue: string) => {
    this.setState({ inputValue });
  };
  handleKeyDown = (event: SyntheticKeyboardEvent<HTMLElement>) => {
    const { inputValue, value } = this.state;
    if (!inputValue) return;
    switch (event.key) {
      case "Enter":
      case "Tab":
        console.group("Value Added");
        console.log(value);
        console.groupEnd();
        this.setState({
          inputValue: "",
          value: [...value, createOption(inputValue)]
        });
        event.preventDefault();
    }
  };
  render() {
    const { inputValue, value } = this.state;
    return (
      <CreatableSelect
        components={components}
        inputValue={inputValue}
        isClearable
        isMulti
        menuIsOpen={false}
        onChange={this.handleChange}
        onInputChange={this.handleInputChange}
        onKeyDown={this.handleKeyDown}
        placeholder="Type something and press enter..."
        value={value}
      />
    );
  }
}

推荐答案

具体类型取决于泛型类型参数 OptionType.OptionType 的默认类型是 { label: string;值:字符串 } 您正在使用的类型.

The specific types depend on a generic type parameter OptionType. The default type for OptionType is the { label: string; value: string } type which you are using.

我认为您遇到的问题是由于您环境中的类型包不正确/过时造成的.

新 CodeSandbox,我安装了@types/react-selectonChange函数的定义是:

In a new CodeSandbox, where I installed @types/react-select, the definition for the onChange function is:

onChange?: (value: ValueType<OptionType, IsMulti>, action: ActionMeta<OptionType>) => void;

这个 ValueType 实用程序类型基本上是说,在单个选择上,您有一个选项或 null,在多个选择上,您有一个 array 选项.

This ValueType utility type basically says that on a single select you have either an option or null and on on multiple select you have an array of options.

export type ValueType<OptionType extends OptionTypeBase, IsMulti extends boolean> = IsMulti extends true
    ? OptionsType<OptionType>
    : OptionType | null;

export type OptionsType<OptionType extends OptionTypeBase> = ReadonlyArray<OptionType>;


我不确定您链接的沙箱如何对其类型进行排队,因为 @types/react-select 包未包含在 package.json 中.但是如果我转到定义"我从 /sandbox/node_modules/@types/react-select/src 文件中得到一个定义.这些是我看到的类型:


I'm not sure how your linked sandbox is enqueing its types because the @types/react-select package is not included in the package.json. But if I "Go To Definition" I get a definition from a /sandbox/node_modules/@types/react-select/src file. These are the types that I see:

onChange?: (value: ValueType<OptionType>, action: ActionMeta) => void;

export type ValueType<OptionType extends OptionTypeBase> = OptionType | OptionsType<OptionType> | null | undefined;

export type OptionsType<OptionType extends OptionTypeBase> = ReadonlyArray<OptionType>;


那么有什么区别?

在第一种情况下,我们知道由于您有多项选择,您将始终收到一系列选项.

In the first case, we know that since you have a multi-select you will always receive an array of options.

在第二种情况下没有 IsMulti 标志,因此类型声明您可以接收数组或单个选项(或 nullundefined).您的 handleChange 函数只能处理一个数组,因此它不能用作 onChange 处理程序,因为它无法处理它可能收到的所有可能的参数.

In the second case there is no IsMulti flag, so the types state that you could receive an array or a single option (or null or undefined). Your handleChange function can only handle an array, so it can't be used as an onChange handler since it can't handle all of the possible arguments that it might receive.

使用正确的包类型,您之前尝试的几乎是正确的.唯一的问题是数组是readonly,所以我们必须确保我们可以在处理程序和状态中接受ReadonlyArray.

With the correct package types, what you tried before is almost correct. The only issue is that the array is readonly, so we have to make sure that we can accept a ReadonlyArray in both the handler and the state.

仅供参考,这些函数没有在我直觉上期望的地方被调用.handleChange 在删除标签时调用,但在按 Enter 添加新标签时不会调用.因此,您需要查看文档和/或尝试各种回调.有 六个道具CreatableSelect -- 两个设置和四个回调.

FYI these functions aren't being called where I would intuitively expect. handleChange is called when removing a tag but not when adding a new one by pressing enter. So you'll want to check out the docs and/or play with the various callbacks. There are six props which are only on CreatableSelect -- two settings and four callbacks.

使用 @types/react-select 4.0.13 和 react-select 4.3.0,这应该可以修复所有 Typescript 错误:

This should fix all of your Typescript errors, using @types/react-select 4.0.13 and react-select 4.3.0:

import React, { Component } from "react";
import CreatableSelect from "react-select/creatable";
import { ActionMeta, InputActionMeta } from "react-select";

const components = {
  DropdownIndicator: null
};

const createOption = (label: string) => ({
  label,
  value: label
});

type MyOption = ReturnType<typeof createOption>;
// or type MyOption = { label: string;  value: string; }

interface MyState {
  inputValue: string;
  value: ReadonlyArray<MyOption>;
}

interface MyProps {
  // are there any?
}

export default class CreatableInputOnly extends Component<MyProps, MyState> {
  state: MyState = {
    inputValue: "",
    value: []
  };
  handleChange = (
    value: ReadonlyArray<MyOption>,
    meta: ActionMeta<MyOption>
  ) => {
    console.log("value", value, "meta", meta);
    this.setState({ value });
  };
  handleInputChange = (inputValue: string, meta: InputActionMeta) => {
    this.setState({ inputValue });
  };
  handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
    const { inputValue, value } = this.state;
    if (!inputValue) return;
    switch (event.key) {
      case "Enter":
      case "Tab":
        console.group("Value Added");
        console.log(value);
        console.groupEnd();
        this.setState({
          inputValue: "",
          value: [...value, createOption(inputValue)]
        });
        event.preventDefault();
    }
  };
  render() {
    const { inputValue, value } = this.state;
    return (
      <CreatableSelect
        components={components}
        inputValue={inputValue}
        isClearable
        isMulti
        menuIsOpen={false}
        onChange={this.handleChange}
        onInputChange={this.handleInputChange}
        onKeyDown={this.handleKeyDown}
        placeholder="Type something and press enter..."
        value={value}
      />
    );
  }
}

代码沙盒链接

这篇关于将 Typescript 类型添加到 react-select onChange 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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