使用 React Hooks 在 mouseenter 和 mouseleave 上隐藏和显示模式
我尝试在 mouseenter
和 mouseleave
上添加条件,但是模式不起作用,但是当我尝试创建 button onClick={() =>{openModal();}}
模态会出现.你能告诉我我的代码有什么问题以及哪一部分.
I tried adding the condition on mouseenter
and mouseleave
however the modal is not working but when I tried to create a button onClick={() => {openModal();}}
the modal will show up. Can you please tell me what's wrong on my code and which part.
const openModal = event => {
if (event) event.preventDefault();
setShowModal(true);
};
const closeModal = event => {
if (event) event.preventDefault();
setShowModal(false);
};
function useHover() {
const ref = useRef();
const [hovered, setHovered] = useState(false);
const enter = () => setHovered(true);
const leave = () => setHovered(false);
useEffect(() => {
if (ref.current.addEventListener('mouseenter', enter)) {
openModal();
} else if (ref.current.addEventListener('mouseleave', leave)) {
closeModal();
}
return () => {
if (ref.current.addEventListener('mouseenter', enter)) {
openModal();
} else if (ref.current.addEventListener('mouseleave', leave)) {
closeModal();
}
};
}, [ref]);
return [ref, hovered];
}
const [ref, hovered] = useHover();
<div className="hover-me" ref={ref}>hover me</div>
{hovered && (
<Modal active={showModal} closeModal={closeModal} className="dropzone-modal">
<div>content here</div>
</Modal>
)}
我几乎放弃并通过了这个,但这是一个有趣的问题.
I almost gave up and passed on this but it was an interesting problem.
问题:
第一个主要问题是
useHover
钩子的useEffect
钩子,它需要添加/删除 both 事件侦听器同时,当 ref 的当前组件挂载和卸载时.关键部分是钩子需要缓存效果钩子中的当前引用,以便清理函数正确运行.
The first main issue is with the
useEffect
hook of youruseHover
hook, it needs to add/remove both event listeners at the same time, when the ref's current component mounts and unmounts. The key part is the hook needs to cache the current ref within the effect hook in order for the cleanup function to correctly function.
第二个问题是您没有删除返回的效果挂钩清理函数中的侦听器.
The second issue is you aren't removing the listener in the returned effect hook cleanup function.
第三个问题是 EventTarget.addEventListener()
返回 undefined
,这是一个假值,因此你的钩子永远不会调用 modalOpen
或 modalClose
The third issue is that EventTarget.addEventListener()
returns undefined
, which is a falsey value, thus your hook never calls modalOpen
or modalClose
最后一个问题是模式打开/关闭状态/回调与 useHover
钩子的实现耦合.(这很好,但是在这种级别的耦合下,您还不如将钩子逻辑直接放在父组件中,完全没有必要将其分解为可重用的钩子!)
The last issue is with the modal open/close state/callbacks being coupled to the useHover
hook's implementation. (this is fine, but with this level of coupling you may as well just put the hook logic directly in the parent component, completely defeating the point of factoring it out into a reusable hook!)
解决方案
这是我能够开始工作的内容:
Here's what I was able to get working:
const useHover = () => {
const ref = useRef();
const _ref = useRef();
const [hovered, setHovered] = useState(false);
const enter = () => setHovered(true);
const leave = () => setHovered(false);
useEffect(() => {
if (ref.current) {
_ref.current = ref.current; // cache external ref value for cleanup use
ref.current.addEventListener("mouseenter", enter);
ref.current.addEventListener("mouseleave", leave);
}
return () => {
if (_ref.current) {
_ref.current.removeEventLisener("mouseenter", enter);
_ref.current.removeEventLisener("mouseleave", leave);
}
};
}, []);
return [ref, hovered];
};
注意:正如我怀疑的那样,将它与模态一起使用似乎存在交互问题,但也许您的模态效果更好.
Note: using this with a modal appears to have interaction issues as I suspected, but perhaps your modal works better.