Definitelytyped: [@types/react] tipo de retorno useRef colide com o tipo de prop ref

Criado em 19 mai. 2019  ·  12Comentários  ·  Fonte: DefinitelyTyped/DefinitelyTyped

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'.

Comentários muito úteis

Uma solução um pouco mais limpa é definir o valorInicial como nulo na chamada da função useRef

const componentRef = useRef<HTMLDivElement>(null);

isso garante que componentRef = HTMLDivElement | null que é o que a prop ref está esperando em vez de HTMLDivElement | undefined .

Todos 12 comentários

EDIT 2: Desconsidere minha solução, use a abaixo :)

Atualmente estou com o mesmo problema, por acaso você já encontrou uma solução?

EDIT: agora estou usando esta solução, reconhecidamente não tão bonita:

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

Encontrado aqui: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/28884#issuecomment -471341041

Uma solução um pouco mais limpa é definir o valorInicial como nulo na chamada da função useRef

const componentRef = useRef<HTMLDivElement>(null);

isso garante que componentRef = HTMLDivElement | null que é o que a prop ref está esperando em vez de HTMLDivElement | undefined .

@shane935 você fez meu dia senhor 🙌🏻

Parece-me que undefined deve ser adicionado a RefObject<T>.current como:

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

então ele lê

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

Não é um bug, está pegando um erro de digitação legítimo.

Para obter mais detalhes, consulte https://github.com/DefinitelyTyped/DefinitelyTyped/pull/38228#issuecomment -529749802

Assim como @Jessidhia diz, não é um bug, talvez você deva escrever assim.

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;

Não tenho certeza se isso resolverá o problema de todos, e não sou especialista nessas coisas, mas depois de olhar para as tipagens do que eu estava passando como ref e o tipo de ref real do componente para o qual eu estava passando o ref , parecia que eu tinha as interfaces erradas.

Inicialmente, eu tinha uma interface de adereços assim para o componente de recebimento:

type TextboxProps = CustomProps & React.HTMLProps<HTMLInputElement>

que alterei para:

type TextboxProps = CustomProps & React.HTMLAttributes<HTMLInputElement>

o erro de digitação então desapareceu.

Não vou fingir que sei mais do que sei, mas olhando para as tipagens para a interface HTMLProps e o tipo de função React.forwardRef() você pode ver que está usando RefAttributes. Logo acima disso, você pode ver os ClassAttributesdigite que HTMLPropsestá se estendendo, dos quais define o LegacyReftipo que acredito estar causando meu problema de digitação.

Parece que este projeto tem 3 sobrecargas para useRef() , precisamos de todos os 3? Parece que o caso useRef<T>(null) é o que os desenvolvedores usarão na maioria das vezes.

    function useRef<T>(initialValue: T): MutableRefObject<T>;
    function useRef<T>(initialValue: T|null): RefObject<T>;
    function useRef<T = undefined>(): MutableRefObject<T | undefined>;
  1. Qual é o caso de uso esperado das duas sobrecargas mutáveis?
  2. Existe alguma outra maneira que isso pode ser suportado para que os usuários possam encontrar mais facilmente a sobrecarga "correta"?

Eu tenho RefObject :

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

Eu passo para o meu componente Panel como prop ref :

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

Eu tento consumir com forwardRef , fica MutableRefObject :

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

Agora não consigo consumir a propriedade .current :

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

@Jessidhia @osf2e sua sugestão não parece aplicável aqui.

A solução alternativa que tive que recorrer:

        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`;
            }

Usando react-native-web, tive que usar.

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

Eu tive esse problema com um Ref para um elemento Input
Então eu mudei de useRef<HTMLDivElement>() -> useRef<HTMLInputElement>() e funcionou bem

@joshribakoff Você também pode digitar os parâmetros diretamente

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

Dessa forma, você não deve ter que typecast ao acessar seu ref.
Mas ainda não entendo porque temos que fazer isso...

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

jbreckmckye picture jbreckmckye  ·  3Comentários

demisx picture demisx  ·  3Comentários

jgoz picture jgoz  ·  3Comentários

JudeAlquiza picture JudeAlquiza  ·  3Comentários

csharpner picture csharpner  ·  3Comentários