@types/16.8.17
, и у меня возникли проблемы.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'.
РЕДАКТИРОВАТЬ 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.
Похоже, в этом проекте есть 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>;
У меня есть RefObject
:
Я передаю его моему компоненту Panel
в качестве реквизита ref
:
Я пытаюсь использовать w/ forwardRef
, он становится MutableRefObject
:
Теперь я не могу использовать свойство .current
:
@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>) => {
Таким образом, вам не нужно приводить типы при доступе к вашей ссылке.
Но я все еще не понимаю, почему мы должны это делать...
Самый полезный комментарий
Чуть более аккуратное решение — установить для initialValue значение null в вызове функции useRef.
const componentRef = useRef<HTMLDivElement>(null);
это гарантирует, что componentRef =
HTMLDivElement | null
это то, что ожидает свойство ref , а неHTMLDivElement | undefined
.