reactjs - React/Typescript - 使用 ref 时出现 typescript 错误 - 类型 'current' 上不存在属性 '(instance: HTMLInputElement | null) => void'

标签 reactjs typescript

我有一个接收 ref 属性的组件:

import React, {forwardRef, ReactElement, ReactNode, HTMLProps, useRef} from 'react'
import styles from './index.module.css'
import classNames from 'classnames'
import { IconFa } from '../icon-fa'
import { useStableId } from '../use-stable-id'

export interface Props extends HTMLProps<HTMLInputElement> {
  // An icon component to show on the left.
  icon?: ReactNode
  // A help text tooltip to show on the right.
  help?: string
  // A clear text tooltip to show on the right.
  clear?: string
  // Pass an onHelp click handler to show a help button.
  onHelp?: () => void
  // Pass an onClear click handler to show a clear button.
  onClear?: () => void
  errorMessage?: ReactNode
  label?: string
  hideLabel?: boolean
}

export const FormInput = forwardRef<HTMLInputElement, Props>(function FormInput(props, ref): ReactElement {
  const { id, icon, help, hideLabel, errorMessage, onHelp, onClear, ...rest } = props
  const stableId = useStableId()
  const inputId = id ? id : stableId

  console.log(ref.current)

  const inputClassName = classNames(
    styles.input,
    icon && styles.hasLeftIcon,
    (help || onHelp || onClear) && styles.hasRightIcon
  )

  const labelClassName = classNames(
    styles.label,
    Boolean(props.value) && styles.hasValue,
    props['aria-invalid'] && styles.hasError,
    props.className
  )

  return (
    <div className={labelClassName}>
      {!hideLabel && (
        <label className={styles.labelText} htmlFor={inputId}>
          {props.label}
          {props.required && '*'}
        </label>
      )}
      <div className="relative">
        {icon && <div className={styles.leftIcon}>{icon}</div>}
        <input
          {...rest}
          id={inputId}
          ref={ref}
          aria-invalid={props['aria-invalid']}
          aria-label={props.hideLabel ? props.label : undefined}
          className={inputClassName}
        />
        {onClear && <ClearIcon {...props} />}
        {!onClear && (help || onHelp) && <HelpIcon {...props} />}
      </div>
      {props['aria-invalid'] && <span className={styles.error}>{errorMessage}</span>}
    </div>
  )
})

function HelpIcon(props: Props) {
  if (props.onHelp) {
    return (
      <button type="button" className={styles.rightIcon} aria-label={props.help} onClick={props.onHelp}>
        <IconFa icon={['far', 'info-circle']} title={props.help} />
      </button>
    )
  }

  return (
    <div className={styles.rightIcon} title={props.help}>
      <IconFa icon={['far', 'info-circle']} />
    </div>
  )
}

function ClearIcon(props: Props) {
  return (
    <button type="button" className={styles.rightIcon} aria-label={props.clear} onClick={props.onClear}>
      <IconFa icon={['far', 'times']} title={props.clear} />
    </button>
  )
}

我想检查输入字段是否处于事件状态。我尝试这样做:

const active = document.activeElement === ref.current

但是,我收到以下错误:

Property 'current' does not exist on type '(instance: HTMLInputElement | null) => void'.

我应该如何正确使用这个forwardedRef?

最佳答案

在这种情况下,组件 A(此处 FormInput )访问 ref通过 forwardRef 支撑,通常将其转发到内部组件 B(此处为 <input> ),但同时 A 需要引用 B 的内部功能(此处是为了测试其焦点)。

问题是,如果消费父组件 P 没有向 ref 提供任何实际的引用对象A 的支柱,ref A 内是 null 。它还可能收到 callback ref表单(因此是错误消息中的类型)。

对于这种情况,您实际上需要在内部管理对 B 的引用(A 中的 useRef)。然后你用 useImperativeHandle 将它暴露给 P与 forwardRef 结合,如所描述的,例如在 https://www.carlrippon.com/using-a-forwarded-ref-internally/

import React, { forwardRef, useImperativeHandle, useRef } from 'react'

export const FormInput = forwardRef<HTMLInputElement, Props>(function FormInput(props, forwardedRef) {
  const internalRef = useRef<HTMLInputElement>(null)

  // Do something internally with the ref...
  console.log(internalRef.current)

  // Expose the ref externally
  useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
    forwardedRef,
    () => internalRef.current
  )

  return (
    <input ref={internalRef} />
  )
})

关于reactjs - React/Typescript - 使用 ref 时出现 typescript 错误 - 类型 'current' 上不存在属性 '(instance: HTMLInputElement | null) => void',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73724784/

相关文章:

javascript - 使用 react-router 使用react的 url 的问题

typescript - Angular2通过属性将函数传递给指令

javascript - (React/Redux) Redux 操作中的异步问题

javascript - Flowtype/Typescript 通用获取属性

html - 无法在单个页面应用程序( Angular )中显示多个组件

javascript - 如何定义[key, val]的TS类型?

javascript - 在 gulp 和 nodejs 中使用 Typescript 时未定义对 require 和 exports 的引用

reactjs - 如何使用 Material UI 处理简单表格中一行的点击

javascript - 使用 React 将索引作为状态传递给组件

reactjs - 使用 HTTPS 在 AWS S3 上部署 ReactJS 应用程序