我有一个简单的函数React组件,用于我正在处理的可重复使用的工具提示,我已经准备好了测试的一切,但我在函数if (node.current.contains(target))...
的这一行,在我的useRef元素node
上收到了一个TypeScript错误"可能未定义",我不知道如何修复它。
我最初尝试将useRef的类型设置为:
const node = useRef()<HTMLDivElement>(null);
然后在我的函数中调用它,比如:
const handleHover = ({ target }) => {
if (node?.current.contains(target)) {
....
}
}
但这会在定义级别引发错误"无法调用类型缺少调用签名的表达式。类型"MutableRefObject"没有兼容的调用签名。",然后在我的函数中引发错误"Expected a expression"。
我确信答案是显而易见的,我只是盯着这个看了太久了,但我现在被难住了,所以我们非常感谢任何反馈。
我的当前组件供完全参考:
import React, { useEffect, useRef, useState } from 'react';
import './tooltip-style.scss'
import cx from 'classnames';
type Props = {
title: string;
position: string;
children: React.ReactNode;
};
const Tooltip = (props: Props) => {
const { title, position, children } = props;
const node = useRef();
const [isVisible, setState] = useState(false);
const handleHover = ({ target }) => {
if (node.current.contains(target)) {
// hover over
return;
}
// hover out
setState(false);
};
useEffect(() => {
document.addEventListener('mouseover', handleHover);
return () => {
document.removeEventListener('mouseout', handleHover);
};
}, []);
return (
<div className={'.container'}
data-testid="tooltip"
ref={node}
onMouseEnter={() => setState(!isVisible)}
>
<div data-testid="tooltip-placeholder">{children}</div>
{isVisible && (
<div
className={cx('.tooltipContent', [position])}
data-testid="tooltip-content"
>
<span className={'.arrow'}></span>
{title}
</div>
)}
</div>
);
};
export default Tooltip;
您可以通过如下方式(使用您的示例(键入ref来解决此问题:
const node = useRef() as MutableRefObject<HTMLDivElement>;
只要确保你也有必要的进口:
import React, { useRef, MutableRefObject } from 'react';
您已接近目标,但存在两个语法错误。
const node = useRef()<HTMLDivElement>(null);
useRef()
调用该函数,然后用(null)
调用该函数的结果。你需要去掉第一个括号,只调用钩子一次:
const node = useRef<HTMLDivElement>(null);
if (node?.current.contains(target)) {
始终定义变量node
。它是current
属性,可能是null
。因此,将可选的链接问号移到current
:之后
if (node.current?.contains(target)) {
如果要向handleHover
的参数添加类型,则会出现一个小问题,因为MouseEvent
的target
属性是EventTarget
或null
。但是.contains()
期望Node
。我不确定你是否会把无效的论点视为";悬停在";或";悬停在外";。它不太可能在现实中发生,但为了类型安全,我们应该检查它。
const node = useRef<HTMLDivElement>(null);
const [isVisible, setState] = useState(false);
const handleHover = ({ target }: MouseEvent) => {
if (target instanceof Node && node.current?.contains(target)) {
// hover over
return;
}
// hover out
setState(false);
};
打字游戏场链接