Definitelytyped: [@types/react] Тип возврата useRef конфликтует с типом реквизита ref

Созданный на 19 мая 2019  ·  12Комментарии  ·  Источник: DefinitelyTyped/DefinitelyTyped

  • [x] Я пытался использовать пакет @types/16.8.17 , и у меня возникли проблемы.
  • [x] Я пытался использовать последнюю стабильную версию tsc. https://www.npmjs.com/package/typescript
  • [x] У меня есть вопрос, который не подходит для StackOverflow . (Пожалуйста, задавайте любые соответствующие вопросы там).
Type 'MutableRefObject<HTMLDivElement | undefined>' is not assignable to type 'string | ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined'.
  Type 'MutableRefObject<HTMLDivElement | undefined>' is not assignable to type 'RefObject<HTMLDivElement>'.
    Types of property 'current' are incompatible.
      Type 'HTMLDivElement | undefined' is not assignable to type 'HTMLDivElement | null'.
        Type 'undefined' is not assignable to type 'HTMLDivElement | null'.

Самый полезный комментарий

Чуть более аккуратное решение — установить для initialValue значение null в вызове функции useRef.

const componentRef = useRef<HTMLDivElement>(null);

это гарантирует, что componentRef = HTMLDivElement | null это то, что ожидает свойство ref , а не HTMLDivElement | undefined .

Все 12 Комментарий

РЕДАКТИРОВАТЬ 2: не обращайте внимания на мое решение, используйте приведенное ниже :)

У меня сейчас такая же проблема, вы случайно не нашли решение?

РЕДАКТИРОВАТЬ: сейчас я использую это, по общему признанию, не очень красивое решение:

const inputField = React.useRef() as React.MutableRefObject<HTMLInputElement>;

Найдено здесь: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/28884#issuecomment -471341041

Чуть более аккуратное решение — установить для initialValue значение null в вызове функции useRef.

const componentRef = useRef<HTMLDivElement>(null);

это гарантирует, что componentRef = HTMLDivElement | null это то, что ожидает свойство ref , а не HTMLDivElement | undefined .

@shane935 вы сделали мой день, сэр 🙌🏻

Мне кажется, что undefined следует добавить к RefObject<T>.current , например:

//index.ts, line 80
interface RefObject<T> {
   readonly current: T | null;
}

так это читается

//index.ts, line 80
interface RefObject<T> {
   readonly current: T | null | undefined;
}

Это не ошибка, это обнаружение законной опечатки.

Подробнее см. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/38228#issuecomment -529749802.

Как говорит @Jessidhia , это не ошибка, возможно, вам следует написать так.

import React, {
  forwardRef,
  ForwardRefRenderFunction,
  useImperativeHandle,
  useRef,
  PropsWithChildren,
} from "react";

interface Props {}
interface Ref {
  value: string;
  setValue: (value: string) => void;
}

const InputEmail: ForwardRefRenderFunction<Ref, PropsWithChildren<Props>> = (
  props,
  ref
) => {
  // hooks
  const inputElement = useRef<HTMLInputElement | null>(null);
  useImperativeHandle(ref, () => {
    return {
      value: inputElement.current ? inputElement.current.value : "",
      setValue: (value: string) => {
        inputElement.current && (inputElement.current.value = value);
      },
    };
  });

  // render
  return (
    <div>
      <input
        type="text"
        ref={inputElement}
        defaultValue="[email protected]"
        disabled
      />
    </div>
  );
};

const Component = forwardRef(InputEmail);

export default Component;

Я не уверен, что это решит проблему каждого, и я не эксперт в этом, но после просмотра типизации того, что я передал в качестве ссылки, и фактического типа ссылки компонента, в который я передал ссылку. , казалось, что у меня неправильные интерфейсы.

Изначально у меня был такой интерфейс реквизита для принимающего компонента:

type TextboxProps = CustomProps & React.HTMLProps<HTMLInputElement>

который я изменил на:

type TextboxProps = CustomProps & React.HTMLAttributes<HTMLInputElement>

ошибка при вводе исчезла.

Я не собираюсь притворяться, что знаю больше, чем на самом деле, но глядя на типизацию интерфейса HTMLProps и типа функции React.forwardRef(), вы можете увидеть, что он использует RefAttributes.. Чуть выше вы можете увидеть ClassAttributesвведите этот HTMLPropsрасширяется, из которых определяет LegacyReftype, который, как я считаю, вызывал мою проблему с набором текста.

Похоже, в этом проекте есть 3 перегрузки для useRef() , нужны ли нам все 3? Похоже, что случай useRef<T>(null) — это то, что разработчики будут использовать большую часть времени.

    function useRef<T>(initialValue: T): MutableRefObject<T>;
    function useRef<T>(initialValue: T|null): RefObject<T>;
    function useRef<T = undefined>(): MutableRefObject<T | undefined>;
  1. Каков ожидаемый вариант использования двух изменяемых перегрузок?
  2. Есть ли какой-либо другой способ, которым это может быть поддержано, чтобы пользователям было легче найти «правильную» перегрузку?

У меня есть RefObject :

Screen Shot 2020-08-23 at 1 06 16 PM

Я передаю его моему компоненту Panel в качестве реквизита ref :

Screen Shot 2020-08-23 at 1 06 04 PM

Я пытаюсь использовать w/ forwardRef , он становится MutableRefObject :

Screen Shot 2020-08-23 at 1 06 56 PM

Теперь я не могу использовать свойство .current :

Screen Shot 2020-08-23 at 1 10 27 PM

@Jessidhia @osf2e ваше предложение здесь не применимо.

Обходной путь, к которому мне пришлось прибегнуть:

        if (ref && (ref as RefObject<HTMLDivElement>).current) {
              // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
              (ref as RefObject<
                HTMLDivElement
              >)!.current!.style.height = `${containerHeight}px`;
            }

Используя react-native-web, мне пришлось использовать.

import {RefObject} from 'react';
// ...
const myRef = useRef() as RefObject<View>

У меня была эта проблема с Ref для элемента Input
Итак, я переключился с useRef<HTMLDivElement>() -> useRef<HTMLInputElement>() , и все заработало.

@joshribakoff Вы также можете ввести параметры напрямую

export const Panel = React.forwardRef((props: PanelProps, ref: React.RefObject<HTMLDivElement>) => {

Таким образом, вам не нужно приводить типы при доступе к вашей ссылке.
Но я все еще не понимаю, почему мы должны это делать...

Была ли эта страница полезной?
0 / 5 - 0 рейтинги