Definitelytyped: [@types/react] Le type de retour useRef est en conflit avec le type de prop ref

Créé le 19 mai 2019  ·  12Commentaires  ·  Source: DefinitelyTyped/DefinitelyTyped

  • [x] J'ai essayé d'utiliser le package @types/16.8.17 et j'ai eu des problèmes.
  • [x] J'ai essayé d'utiliser la dernière version stable de tsc. https://www.npmjs.com/package/typescript
  • [x] J'ai une question inappropriée pour StackOverflow . (Veuillez y poser toutes les questions appropriées).
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'.

Commentaire le plus utile

Une solution légèrement plus simple consiste à définir initialValue sur null dans l'appel de fonction useRef

const componentRef = useRef<HTMLDivElement>(null);

cela garantit que componentRef = HTMLDivElement | null qui est ce que la prop ref attend plutôt que HTMLDivElement | undefined .

Tous les 12 commentaires

EDIT 2 : Ne tenez pas compte de ma solution, utilisez celle ci-dessous :)

J'ai actuellement le même problème, avez-vous déjà trouvé une solution par hasard ?

EDIT : J'utilise maintenant cette solution, certes pas si jolie :

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

Trouvé ici : https://github.com/DefinitelyTyped/DefinitelyTyped/issues/28884#issuecomment -471341041

Une solution légèrement plus simple consiste à définir initialValue sur null dans l'appel de fonction useRef

const componentRef = useRef<HTMLDivElement>(null);

cela garantit que componentRef = HTMLDivElement | null qui est ce que la prop ref attend plutôt que HTMLDivElement | undefined .

@shane935 vous avez fait ma journée monsieur 🙌🏻

Il me semble que undefined devrait être ajouté à RefObject<T>.current comme :

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

donc ça se lit

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

Ce n'est pas un bogue, c'est une erreur de frappe légitime.

Pour plus de détails, voir https://github.com/DefinitelyTyped/DefinitelyTyped/pull/38228#issuecomment -529749802

Tout comme @Jessidhia le dit, ce n'est pas un bug, peut-être devriez-vous écrire comme ça.

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;

Je ne suis pas sûr que cela résoudra le problème de tout le monde, et je ne suis pas un expert en la matière, mais après avoir examiné les typages de ce que je transmettais en tant que référence et le type de référence réel du composant dans lequel je transmettais la référence , il semblait que j'avais mal les interfaces.

J'avais initialement une interface d'accessoires comme celle-ci pour le composant de réception :

type TextboxProps = CustomProps & React.HTMLProps<HTMLInputElement>

que j'ai remplacé par :

type TextboxProps = CustomProps & React.HTMLAttributes<HTMLInputElement>

l'erreur de frappe a alors disparu.

Je ne vais pas prétendre en savoir plus que moi, mais en examinant les typages de l'interface HTMLProps et le type de fonction React.forwardRef(), vous pouvez voir qu'il utilise RefAttributes. Juste au-dessus, vous pouvez voir les ClassAttributestapez ce HTMLPropss'étend, dont définit LegacyReftype qui, je crois, était à l'origine de mon problème de frappe.

Il semble que ce projet ait 3 surcharges pour useRef() , avons-nous besoin des 3 ? Il semble que le cas useRef<T>(null) soit celui que les développeurs utiliseront la plupart du temps.

    function useRef<T>(initialValue: T): MutableRefObject<T>;
    function useRef<T>(initialValue: T|null): RefObject<T>;
    function useRef<T = undefined>(): MutableRefObject<T | undefined>;
  1. Quel est le cas d'utilisation attendu des deux surcharges mutables ?
  2. Existe-t-il un autre moyen de prendre en charge cette fonctionnalité pour que les utilisateurs puissent trouver plus facilement la "bonne" surcharge ?

J'ai RefObject :

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

Je le passe à mon composant Panel en tant que prop ref :

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

J'essaie de consommer w/ forwardRef , ça devient MutableRefObject :

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

Je ne peux plus utiliser la propriété .current :

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

@Jessidhia @osf2e votre suggestion ne semble pas applicable ici.

La solution de contournement à laquelle j'ai dû recourir:

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

En utilisant react-native-web, je devais utiliser.

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

J'ai eu ce problème avec une Ref pour un élément Input
Donc je suis passé de useRef<HTMLDivElement>() -> useRef<HTMLInputElement>() et ça a bien fonctionné

@joshribakoff Vous pouvez également taper les paramètres directement

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

De cette façon, vous ne devriez pas avoir à transtyper lors de l'accès à votre ref.
Mais je ne comprends toujours pas pourquoi nous devons faire cela...

Cette page vous a été utile?
0 / 5 - 0 notes