Definitelytyped: [@types/react] useRef-Rückgabetyp kollidiert mit ref-Prop-Typ

Erstellt am 19. Mai 2019  ·  12Kommentare  ·  Quelle: DefinitelyTyped/DefinitelyTyped

  • [x] Ich habe versucht, das @types/16.8.17 -Paket zu verwenden, und hatte Probleme.
  • [x] Ich habe versucht, die neueste stabile Version von tsc zu verwenden. https://www.npmjs.com/package/typescript
  • [x] Ich habe eine Frage, die für StackOverflow ungeeignet ist. (Bitte stellen Sie dort entsprechende Fragen).
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'.

Hilfreichster Kommentar

Eine etwas elegantere Lösung besteht darin, initialValue im useRef-Funktionsaufruf auf null zu setzen

const componentRef = useRef<HTMLDivElement>(null);

dies stellt sicher, dass componentRef = HTMLDivElement | null ist, was die ref prop erwartet, und nicht HTMLDivElement | undefined .

Alle 12 Kommentare

EDIT 2: Ignorieren Sie meine Lösung, verwenden Sie die unten :)

Ich habe aktuell das gleiche Problem, hast du zufällig schon eine Lösung gefunden?

EDIT: Ich benutze jetzt diese, zugegebenermaßen nicht so schöne Lösung:

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

Hier zu finden: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/28884#issuecomment -471341041

Eine etwas elegantere Lösung besteht darin, initialValue im useRef-Funktionsaufruf auf null zu setzen

const componentRef = useRef<HTMLDivElement>(null);

dies stellt sicher, dass componentRef = HTMLDivElement | null ist, was die ref prop erwartet, und nicht HTMLDivElement | undefined .

@shane935 Sie haben mir den Tag versüßt, Sir 🙌🏻

Mir scheint, undefined sollte wie folgt zu RefObject<T>.current hinzugefügt werden:

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

so liest es sich

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

Es ist kein Fehler, es fängt einen legitimen Tippfehler ab.

Weitere Einzelheiten finden Sie unter https://github.com/DefinitelyTyped/DefinitelyTyped/pull/38228#issuecomment -529749802

Genau wie @Jessidhia sagt, es ist kein Fehler, vielleicht solltest du so schreiben.

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;

Ich bin mir nicht sicher, ob dies alle Probleme lösen wird, und ich bin kein Experte für dieses Zeug, aber nachdem ich mir die Eingaben dessen angesehen habe, was ich als Referenz übergeben habe, und den tatsächlichen Referenztyp der Komponente, an die ich die Referenz übergeben habe , es schien, als ob ich die Schnittstellen falsch hatte.

Ich hatte anfangs eine Schnittstelle von Requisiten wie folgt für die empfangende Komponente:

type TextboxProps = CustomProps & React.HTMLProps<HTMLInputElement>

was ich geändert habe zu:

type TextboxProps = CustomProps & React.HTMLAttributes<HTMLInputElement>

der Tippfehler ist dann verschwunden.

Ich werde nicht vorgeben, mehr zu wissen, als ich tue, aber wenn Sie sich die Eingaben für die HTMLProps-Schnittstelle und den Funktionstyp React.forwardRef() ansehen, können Sie sehen, dass sie RefAttributes verwendet. Direkt darüber sehen Sie die KlassenattributeGeben Sie diese HTMLProps einerweitert wird, von denen die LegacyRef definiert wirdTyp, von dem ich glaube, dass er mein Tippproblem verursacht hat.

Es sieht so aus, als hätte dieses Projekt 3 Überladungen für useRef() , brauchen wir alle 3? Es scheint, als würden Entwickler die meiste Zeit den useRef<T>(null) -Fall verwenden.

    function useRef<T>(initialValue: T): MutableRefObject<T>;
    function useRef<T>(initialValue: T|null): RefObject<T>;
    function useRef<T = undefined>(): MutableRefObject<T | undefined>;
  1. Was ist der erwartete Anwendungsfall der beiden veränderlichen Überladungen?
  2. Gibt es eine andere Möglichkeit, dies zu unterstützen, damit Benutzer die "richtige" Überladung leichter finden können?

Ich habe RefObject :

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

Ich übergebe es an meine Panel Komponente als Prop ref :

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

Ich versuche, mit forwardRef zu konsumieren, es wird zu MutableRefObject :

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

Ich kann die Eigenschaft .current jetzt nicht nutzen:

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

@Jessidhia @osf2e Ihr Vorschlag scheint hier nicht anwendbar zu sein.

Der Workaround, auf den ich zurückgreifen musste:

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

Mit React-Native-Web musste ich verwenden.

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

Ich hatte dieses Problem mit einer Ref für ein Input -Element
Also wechselte ich von useRef<HTMLDivElement>() -> useRef<HTMLInputElement>() und es funktionierte gut

@joshribakoff Sie können die Parameter auch direkt eingeben

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

Auf diese Weise sollten Sie beim Zugriff auf Ihre Referenz keine Typumwandlung vornehmen müssen.
Aber ich verstehe immer noch nicht, warum wir das tun müssen ...

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen