我有一个自定义挂钩,可在我的 TS 应用中返回值 useRef
。不幸的是,它抱怨我返回的引用类型,我不知道如何正确输入。
这是我的钩子的样子:
interface MyHookInterface {
someBooleanState: boolean
myRef: HTMLElement | null
}
const useMyHook = (): MyHookInterface => {
const [someBooleanState, setSomeBooleanState] = useState<boolean>(false)
const myRef = useRef<HTMLElement | null>(null)
useEffect(() => {
const el = myRef.current // what type should this be?
// Complaining that el possibly undefined
if(el?.offsetWidth < el?.scrollWidth){
// do stuff
}
}, [])
return {
someBooleanState,
myRef, // Getting: Type 'MutableRefObject<HTMLElement | null>' is missing the following properties from type 'HTMLElement': accessKey, accessKeyLabel, autocapitalize, dir, and 234 more
}
}
正如你在评论中看到的,我的钩子有一些与打字有关的错误:
1- 不知道如何在界面中输入myRef
。请记住,它将用于多种类型的 HTML 元素,因此我无法在此处指定它是 div 还是什么。
2- 不知道如何输入 el
,但对其属性的访问抱怨它是 undefined
如何在钩子中正确键入这些值?
答案 0 :(得分:2)
发生这种情况是因为引用的值存储在“.current”属性下。
即
const Comp = () => {
...
const refVal = React.useRef(2);
console.log(2 === refVal); // false
console.log(2 === refVal.current); // true
...
}
解决方案取决于您的意图 - 如果您想返回 ref 本身,请按照类型错误的建议将接口类型更改为 MutableRefObject<HTMLElement | null>
,否则,将返回值替换为:
return {
someBooleanState,
myRef: myRef.current,
}
如果 el 尚未定义(即尚未分配),由于您使用 undefined
运算符访问该属性,您可能会得到 ?.
,是正确的。
例如
null?.test === undefined; // true
要解决这个问题,请检查是否定义了 el 和可选(尽管接口定义不需要),检查两个值是否都已定义并且是数字(即使用 el && !isNaN(el?.offsetWidth) && !isNaN(el?.scrollWidth) && el.offsetWidth < el.scrollWidth
。或者,使用空合并运算符,如果这适用于您的用例,即 (el?.offsetWidth ?? 0) < (el?.scrollWidth ?? 0)
。
答案 1 :(得分:2)
ref 的类型不仅仅是它所引用的对象。它是一个 React.MutableRefObject
包装它所引用的内容。这就是提供 current
属性以便 ref 可以工作的原因。
如果您仔细考虑 myRef
,您应该会看到您需要的类型。在这种情况下:
React.MutableRefObject<HTMLElement | null>
这让你的钩子返回类型:
interface MyHookInterface {
someBooleanState: boolean
myRef: React.MutableRefObject<HTMLElement | null>
}
其次,这不起作用的原因:
const el = myRef.current // what type should this be?
// Complaining that el possibly undefined
if(el?.offsetWidth < el?.scrollWidth){
// do stuff
}
是因为您的 ref 可能尚未分配值。这意味着 el?.offsetWidth
是 undefined
,因为 el
仍然是 null
。并且 undefined
不是 <
比较中的有效操作数。 (if (undefined < undefined)
没有多大意义)
您可以通过在进行比较之前检查以确保 el
存在来轻松解决此问题:
if (el && el.offsetWidth < el.scrollWidth){
// do stuff
}