0

我很难理解为什么打字稿编译器对我在组件中使用的 forwardRef 不满意。

对于下面的示例,我已将我的代码缩减为基本要素,确保此打字稿错误是代码中唯一出现的错误,根据我的实际代码中的问题:

import { createRef, forwardRef, RefObject } from 'react';

const MyComponent = () => {
    const selectCountryRef = createRef<HTMLSelectElement>();

    return (
        <div>
            <SelectCountry ref={selectCountryRef} />
        </div>
    );
};

const SelectCountry = forwardRef((ref?: RefObject<HTMLSelectElement>) => {
    return (
        <FormFieldSelect ref={ref} />
    );
});

const FormFieldSelect = ({ ref }) => {
    return (
        <div>
            <select ref={ref}>
            </select>
        </div>
    );
};

当试图编译这个时,我得到了错误:

Property 'current' is missing in type '{ ref: RefObject<HTMLSelectElement>; }' but required in type 'RefObject<HTMLSelectElement>'.

在 VSCode 中,<SelectCountry ...是 IDE 发牢骚的地方,确切的消息是:

const SelectCountry: ForwardRefExoticComponent<RefObject<HTMLSelectElement> & RefAttributes<unknown>> Property 'current' is missing in type '{ ref: RefObject<HTMLSelectElement>; }' but required in type 'RefObject<HTMLSelectElement>'.ts(2741) index.d.ts(85, 18): 'current' is declared here.

我只是不明白为什么我会收到这个错误。

目前使用 React 17.0.2

4

2 回答 2

2

forwardRefprops首先使用参数调用,然后使用ref参数调用。

ForwardRefRenderFunction使用ref?: RefObject<HTMLSelectElement>第一个参数是道具。就 TypeScript 而言,props 的类型SelectCountry是 a RefObject<HTMLSelectElement>。这就是您收到错误的原因:

类型中缺少属性“当前”,{ ref: RefObject<HTMLSelectElement>; }但类型中需要RefObject<HTMLSelectElement>


@jeffreyquan 的回答向您展示了一个正确输入的解决方案,所以我不会重复他们写的所有内容。您可以通过在函数上设置泛型类型参数来为propsand分配类型,就像他们向您展示的那样。refforwardRef

您还可以通过注释内部函数的propsandref参数来分配类型,就像您尝试做的那样,但您需要确保它正确完成。如果您没有分配任何类型,props那么它会被推断为PropsWithChildren<{}>这里实际上很好。所以这有效:

const SelectCountry = forwardRef((props, ref: ForwardedRef<HTMLSelectElement>) => {
    return (
        <FormFieldSelect ref={ref} />
    );
});

为了在严格模式下通过类型检查,您需要更改RefObjectForwardedRef. 这允许回调 refs 和null.

于 2021-05-24T09:06:53.320 回答
2

试试下面的。我添加了一个useEffect和一个console.logMyComponent表明它正在工作。我对您分配ref?: RefObject<HTMLSelectElement>的方式感到困惑,SelectCountry并认为这是导致错误的原因。我已经展示了如何forwardRef在代码片段中分配类型,即forwardRef<RefElementType,ComponentPropsType>. FormFieldSelect也必须是一个forwardRef组件。

import React, { useEffect, createRef, forwardRef } from 'react'

export const MyComponent = () => {
  const selectCountryRef = createRef<HTMLSelectElement>()

  useEffect(() => {
    console.log(selectCountryRef.current)
  }, [selectCountryRef])

  return (
    <div>
      <SelectCountry ref={selectCountryRef} />
    </div>
  )
}

interface SelectCountryProps {}

const SelectCountry = forwardRef<HTMLSelectElement, SelectCountryProps>(
  (props, ref) => {
    return <FormFieldSelect ref={ref} />
  },
)

interface FormFieldSelectProps {}

const FormFieldSelect = forwardRef<HTMLSelectElement, FormFieldSelectProps>(
  (props, ref) => {
    return (
      <div>
        <select ref={ref}></select>
      </div>
    )
  },
)
于 2021-05-21T15:51:02.620 回答