[英]Detect click outside component react hooks
I am trying to use react hooks to determine if a user has clicked outside an element.我正在尝试使用反应钩子来确定用户是否在元素外单击。 I am using
useRef
to get a reference to the element.我正在使用
useRef
来获取对元素的引用。
Can anyone see how to fix this.任何人都可以看到如何解决这个问题。 I am getting the following errors and following answers from here .
我从这里收到以下错误和以下答案。
Property 'contains' does not exist on type 'RefObject'
“RefObject”类型上不存在属性“包含”
This error above seems to be a typescript issue.上面的这个错误似乎是一个打字稿问题。
There is a code sandbox here with a different error.这里有一个代码沙箱,有不同的错误。
In both cases it isn't working.在这两种情况下,它都不起作用。
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
const Menu = () => {
const wrapperRef = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(true);
// below is the same as componentDidMount and componentDidUnmount
useEffect(() => {
document.addEventListener('click', handleClickOutside, true);
return () => {
document.removeEventListener('click', handleClickOutside, true);
};
}, []);
const handleClickOutside = event => {
const domNode = ReactDOM.findDOMNode(wrapperRef);
// error is coming from below
if (!domNode || !domNode.contains(event.target)) {
setIsVisible(false);
}
}
return(
<div ref={wrapperRef}>
<p>Menu</p>
</div>
)
}
the useRef API should be used like this: useRef API应该像这样使用:
import React, { useState, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
function App() {
const wrapperRef = useRef(null);
const [isVisible, setIsVisible] = useState(true);
// below is the same as componentDidMount and componentDidUnmount
useEffect(() => {
document.addEventListener("click", handleClickOutside, false);
return () => {
document.removeEventListener("click", handleClickOutside, false);
};
}, []);
const handleClickOutside = event => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setIsVisible(false);
}
};
return (
isVisible && (
<div className="menu" ref={wrapperRef}>
<p>Menu</p>
</div>
)
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Check out this library from Andarist called use-onclickoutside .查看来自Andarist 的这个名为use-onclickoutside 的库。
import * as React from 'react'
import useOnClickOutside from 'use-onclickoutside'
export default function Modal({ close }) {
const ref = React.useRef(null)
useOnClickOutside(ref, close)
return <div ref={ref}>{'Modal content'}</div>
}
An alternative solution is to use a full-screen invisible box.另一种解决方案是使用全屏隐形框。
import React, { useState } from 'react';
const Menu = () => {
const [active, setActive] = useState(false);
return(
<div>
{/* The menu has z-index = 1, so it's always on top */}
<div className = 'Menu' onClick = {() => setActive(true)}
{active
? <p> Menu active </p>
: <p> Menu inactive </p>
}
</div>
{/* This is a full-screen box with z-index = 0 */}
{active
? <div className = 'Invisible' onClick = {() => setActive(false)}></div>
: null
}
</div>
);
}
And the CSS:和 CSS:
.Menu{
z-index: 1;
}
.Invisible{
height: 100vh;
left: 0;
position: fixed;
top: 0;
width: 100vw;
z-index: 0;
}
I have created this common hook, which can be used for all divs which want this functionality.我创建了这个通用钩子,可用于所有需要此功能的 div。
import { useEffect } from 'react';
/**
*
* @param {*} ref - Ref of your parent div
* @param {*} callback - Callback which can be used to change your maintained state in your component
* @author Pranav Shinde 30-Nov-2021
*/
const useOutsideClick = (ref, callback) => {
useEffect(() => {
const handleClickOutside = (evt) => {
if (ref.current && !ref.current.contains(evt.target)) {
callback(); //Do what you want to handle in the callback
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
});
};
export default useOutsideClick;
Usage -用法 -
import React, { useRef } from 'react';
import useOutsideClick from '../../../../hooks/useOutsideClick';
const ImpactDropDown = ({ setimpactDropDown }) => {
const impactRef = useRef();
useOutsideClick(impactRef, () => setimpactDropDown(false)); //Change my dropdown state to close when clicked outside
return (
<div ref={impactRef} className="wrapper">
{/* Your Dropdown or Modal */}
</div>
);
};
export default ImpactDropDown;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.