手动设置电流时,我在 useRef() 钩子上使用啥打字稿类型?
Posted
技术标签:
【中文标题】手动设置电流时,我在 useRef() 钩子上使用啥打字稿类型?【英文标题】:What typescript type do I use with useRef() hook when setting current manually?手动设置电流时,我在 useRef() 钩子上使用什么打字稿类型? 【发布时间】:2020-01-20 20:30:04 【问题描述】:如何通过 Typescript 将 React ref 用作可变实例?当前属性的类型似乎是只读的。
我正在使用 React + Typescript 开发一个库,该库与不是由 React 呈现的输入字段进行交互。我想捕获对 html 元素的引用,然后将 React 事件绑定到它。
const inputRef = useRef<HTMLInputElement>();
const elementId, handler = props;
// Bind change handler on mount/ unmount
useEffect(() =>
inputRef.current = document.getElementById(elementId);
if (inputRef.current === null)
throw new Exception(`Input with ID attribute $elementId not found`);
handler(inputRef.current.value);
const callback = debounce((e) =>
eventHandler(e, handler);
, 200);
inputRef.current.addEventListener('keypress', callback, true);
return () =>
inputRef.current.removeEventListener('keypress', callback, true);
;
);
它会产生编译器错误:semantic error TS2540: Cannot assign to 'current' because it is a read-only property.
我也试过const inputRef = useRef< current: HTMLInputElement >();
这导致这个编译器错误:
Type 'HTMLElement | null' is not assignable to type ' current: HTMLInputElement; | undefined'.
Type 'null' is not assignable to type ' current: HTMLInputElement; | undefined'.
【问题讨论】:
我认为HTMLInputElement
是正确的,但是inputRef最初应该设置为null
,useRef<HTMLInputElement(null)
我也是这么想的。如果 ref 在 React 的渲染期间被捕获 - <input ref=myRef />
- 没有设置 myRef.current = ...
这可能会有所帮助:github.com/DefinitelyTyped/DefinitelyTyped/issues/… 特别是 ref7
【参考方案1】:
是的,这是打字方式的一个怪癖:
function useRef<T>(initialValue: T): MutableRefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T>;
如果初始值包含null
,但指定的类型参数不包含,则将其视为不可变RefObject
。
当您执行useRef<HTMLInputElement>(null)
时,您遇到了这种情况,因为T
被指定为HTMLInputElement
,而null
被推断为HTMLInputElement | null
。
您可以通过以下方式解决此问题:
useRef<HTMLInputElement | null>(null)
那么T
是HTMLInputElement | null
,它与第一个参数的类型相匹配,因此您点击第一个覆盖并获得一个可变引用。
【讨论】:
谢谢!这很有意义,并且可以编译我的代码。我使用const inputRef = useRef<HTMLElement | null>(null);
来避免来自inputRef.current = document.getElementById(elementId);
的编译器错误不知道这是否值得编辑。
是的,如果您不需要来自 ref 的任何特定于输入的属性,那么我会做您所做的并扩大您注释 ref 的类型;如果您确实需要特定于输入的属性,我可能会在分配之前执行getElementById(elementId) as HTMLInputElement
。
作为对其他任何人的参考,我发现如果没有 useRef 钩子就无法做到这一点, createRef 不允许这样做。也许有办法,但我找不到。
似乎不适用于变量(在 useEffect 中分配)const shaderMat: React.RefObject<THREE.ShaderMaterial|null> = useRef(null);
不允许我执行 shaderMat.current = mat;
,因为 curretn 是只读的。
@AmbroiseRabier 您已将shaderMat
明确注释为RefObject
,这是不可变类型,所以是的,它不会让您在useEffect 中对其进行变异。您需要使用useRef
的类型参数来控制类型,而不是变量本身的注释。以上是关于手动设置电流时,我在 useRef() 钩子上使用啥打字稿类型?的主要内容,如果未能解决你的问题,请参考以下文章