使用钩子检测 React 组件外的点击 [英] Detect click outside React component using hooks

查看:39
本文介绍了使用钩子检测 React 组件外的点击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现我在应用程序中重用了当用户在元素外单击时我可以隐藏它的行为.

随着钩子的引入,我是否可以将其放入钩子中并在组件之间共享以节省我在每个组件中编写相同的逻辑?

我已经在一个组件中实现了一次,如下所示.

const Dropdown = () =>{const [isDropdownVisible, setIsDropdownVisible] = useState(false);const wrapperRef = useRef(null);const handleHideDropdown = (事件:KeyboardEvent) =>{if (event.key === 'Escape') {setIsDropdownVisible(false);}};const handleClickOutside = (事件:事件) =>{如果 (wrapperRef.current &&!wrapperRef.current.contains(event.target 作为节点)){setIsDropdownVisible(false);}};useEffect(() => {document.addEventListener('keydown', handleHideDropdown, true);document.addEventListener('click', handleClickOutside, true);返回 () =>{document.removeEventListener('keydown', handleHideDropdown, true);document.removeEventListener('click', handleClickOutside, true);};});返回(<DropdownWrapper ref={wrapperRef}><p>下拉菜单</p></DropdownWrapper>);}

解决方案

这是可能的.

您可以创建一个名为 useComponentVisible

的可重用钩子

import { useState, useEffect, useRef } from 'react';导出默认函数 useComponentVisible(initialIsVisible) {const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible);const ref = useRef(null);const handleHideDropdown = (事件:KeyboardEvent) =>{if (event.key === 'Escape') {setIsComponentVisible(false);}};const handleClickOutside = (事件:事件) =>{if (ref.current && !ref.current.contains(event.target as Node)) {setIsComponentVisible(false);}};useEffect(() => {document.addEventListener('keydown', handleHideDropdown, true);document.addEventListener('click', handleClickOutside, true);返回 () =>{document.removeEventListener('keydown', handleHideDropdown, true);document.removeEventListener('click', handleClickOutside, true);};});返回 { ref, isComponentVisible, setIsComponentVisible };}

然后在您希望添加功能的组件中执行以下操作:

const DropDown = () =>{const { ref, isComponentVisible } = useComponentVisible(true);返回 (<div ref={ref}>{isComponentVisible &&(<p>躲起来</p>)}

);}

在此处查找 codesandbox 示例.

I am finding that I am reusing behaviour across an app that when a user clicks outside an element I can hide it.

With the introduction of hooks is this something I could put in a hook and share across components to save me writing the same logic in every component?

I have implemented it once in a component as follows.

const Dropdown = () => {
    const [isDropdownVisible, setIsDropdownVisible] = useState(false);   
    const wrapperRef = useRef<HTMLDivElement>(null);

    const handleHideDropdown = (event: KeyboardEvent) => {
        if (event.key === 'Escape') {
            setIsDropdownVisible(false);
        }
    };

    const handleClickOutside = (event: Event) => {
        if (
            wrapperRef.current &&
            !wrapperRef.current.contains(event.target as Node)
        ) {
            setIsDropdownVisible(false);
        }
    };

    useEffect(() => {
        document.addEventListener('keydown', handleHideDropdown, true);
        document.addEventListener('click', handleClickOutside, true);
        return () => {
            document.removeEventListener('keydown', handleHideDropdown, true);
            document.removeEventListener('click', handleClickOutside, true);
        };
    });

    return(
       <DropdownWrapper ref={wrapperRef}>
         <p>Dropdown</p>
       </DropdownWrapper>
    );
}

解决方案

This is possible.

You can create a reusable hook called useComponentVisible

import { useState, useEffect, useRef } from 'react';

export default function useComponentVisible(initialIsVisible) {
    const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible);
    const ref = useRef<HTMLDivElement>(null);

    const handleHideDropdown = (event: KeyboardEvent) => {
        if (event.key === 'Escape') {
            setIsComponentVisible(false);
        }
    };

    const handleClickOutside = (event: Event) => {
        if (ref.current && !ref.current.contains(event.target as Node)) {
            setIsComponentVisible(false);
        }
    };

    useEffect(() => {
        document.addEventListener('keydown', handleHideDropdown, true);
        document.addEventListener('click', handleClickOutside, true);
        return () => {
            document.removeEventListener('keydown', handleHideDropdown, true);
            document.removeEventListener('click', handleClickOutside, true);
        };
    });

    return { ref, isComponentVisible, setIsComponentVisible };
}

Then in the component you wish to add the functionality to do the following:

const DropDown = () => {

    const { ref, isComponentVisible } = useComponentVisible(true);

    return (
       <div ref={ref}>
          {isComponentVisible && (<p>Going into Hiding</p>)}
       </div>
    );

}

Find a codesandbox example here.

这篇关于使用钩子检测 React 组件外的点击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆