繁体   English   中英

onKeyDown 和 onChange 与 React 和 TypeScript

[英]onKeyDown and onChange with React and TypeScript

我正在尝试使用 TypeScript 将onChangeonKeyDown分配给 Input 组件,这已经失控了。

我有这个Input组件:

import React, { ChangeEvent, KeyboardEvent } from 'react'

import { InputStyle } from './Input-style'

type InputProps = {
  name: string
  value: string | number
  type?: string
  placeholder?: string
  onBlur?: () => void
  onKeyDown?: (e: KeyboardEvent) => void
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void
}

export const Input = (props: InputProps) => (
  <InputStyle
    type={props.type ? props.type : 'text'}
    name={props.name}
    id={props.name}
    placeholder={props.placeholder}
    value={props.value}
    onKeyDown={props.onKeyDown}
    onChange={props.onChange}
    onBlur={props.onBlur}
  />
)

然后我使用该组件做两件事,验证输入的按键是一个数字,然后添加值,似乎很容易的任务就是给我各种关于类型的 TypeScript 错误

import React, { KeyboardEvent, ChangeEvent } from 'react'

export const renderInput = () => {
  const [rate, setRate] = useState<number>(0)

   
  // I want to add the value only if is a number and between 0-1 no letters
  const addRate = (e: KeyboardEvent | ChangeEvent) => {

    const element = e.target as HTMLInputElement
    const value = element.value

    if ('key' in e) {
      const reg = /[0-9]/
      // If is not a letter
      if (reg.test(e.key)) {
        // Add the value but here now it breaks 
        setRate(isNaN(value) || value > 1 ? 0 : value)
      }
    }
  }

  return (
    <Input
     type='number'
     name='Conversion Rate'
     value={rate === 0 ? '' : rate}
     placeholder='Percentage Decimal number'
     onKeyDown={addRate}
     onChange={addRate}
   />
  )
}

但此时 TypeScript 错误与

'string | 类型的参数 0' 不可分配给“SetStateAction”类型的参数

在尝试检查它是否有效之前,我真的很困惑。

错误的原因是因为 HTML 中的字段总是返回文本值,即使它们是type="number"字段。 为了在 state 中设置值,您需要首先将字符串解析为数字,否则您将收到您看到的类型错误,因为您的 state 被键入为数字。

<Input
  type="number"
  value={rate}
  onInput={e => setRate(Number(e.target.value))}
/>

数字字段将只允许有效的数字字符(包括小数和大指数的e )。 所以你不需要在你的代码中做所有的验证; Number()可以解析 number 字段允许的任何内容。

最后,始终使用onInput来捕获输入,因为这也会捕获诸如拖放、剪切和粘贴、数字字段上的向上/向下箭头等内容。

编辑:您说您的评论您不希望 go 的值高于 1。您可以在数字字段上设置最大值和最小值。

<Input type="number" min="0" max="1" />

如果您真的需要在代码中限制值,以下将确保即使高于 1 的值也会被限制回 1。

<Input
  onInput={e => setRate(Math.max(1, Number(e.target.value)))}
/>

我猜element.value是字符串类型。

您可以使用parseInt(element.value)+element.value将其解析为数字

那将是: const value = +element.value

onKeyDown 调度值作为字符,因此 Typescript 冲突类型。

您可以在 parseInt(value, 10) 中进行转换。

您应该注意,字段类型 number 已经只接受数字和指数的“e”。

没有一个答案对我有用,它们可能在原则上听起来是正确的,但根据我的例子,它只是相互冲突。 我正前往 TypeScript 地狱,所以我通过使用常规文本输入和一些正则表达式摆脱了它:

const addRate = (val: string) => {
  // If it's a number and is higher than 1 exit
  if (!isNaN(parseInt(val)) && parseFloat(val) > 1) {
    return
  }

  // Regex to allow only decimal mumbers
  const reg = /^\d*(?:[.]\d*)?$/
  if (reg.test(val)) setRate(val)
}

<Input
  name='Conversion Rate'
  value={rate}
  placeholder='Decimal number - Optional'
  onChange={e => addRate(e.target.value)}
/>

没有输入类型号,没有 keydown 只是正则表达式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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