English 中文(简体)
在点外点击时,停止退缩
原标题:React closing a dropdown when click outside

Building a custom dropdown in React and came across a problem when trying to close it when clicking outside.
So i created generic HOC so i can use it for other ocasions as well.

问题一似乎在通过<代码>ref时并不知情。 从临时到构成部分。

I ve been looking into forwardRef and other tones of examples, but i can t figure it out.
Any idea if it s possible and how i could do it?

Codesand Box Demo

import React, { useState, useRef, useEffect } from "react";

export default function withClickOutside(WrappedComponent) {
  const Component = (props) => {
    const [open, setOpen] = useState(false);

    const ref = useRef();

    useEffect(() => {
      const handleClickOutside = (event) => {
        if (!ref?.current?.contains(event.target)) {
          setOpen(false);
        }
      };
      document.addEventListener("mousedown", handleClickOutside);
    }, [ref]);

    return <WrappedComponent {...props} open={open} setOpen={setOpen} ref={ref}/>;
  };

  return Component;
}

最佳回答
问题回答

www.un.org/Depts/DGACM/index_spanish.htm 简单遵循5个步骤,在使用React Hook在单元外点击时,关闭任何元素的菜单/变化状态。

<>Step 1: 进口使用Ref和定义

import {useRef} from "react"

const catMenu = useRef(null)

<>标准2:使用 React Hook for state chnage (use State)

  const [openSlide, setopenSlide] = useState(""); 

Step 3: Define a javascript function to set state

   const closeOpenMenus = (e)=>{
    if(openSlide && !catMenu.current?.contains(e.target)){
      setopenSlide(false)
    }
}

<>Step 4>: 在号文件内添加有关在任何地方停播的节目。

 document.addEventListener( mousedown ,closeOpenMenus)

Step 5: 选择目标要素(ref={variable_name})

<div ref={catMenu}>... </div>

It is a little diff. from your approach, but this hook can used to wrap your button and menu.

/**
 * This Hook can be used for detecting clicks outside the Opened Menu
 */
function useClickOutside(ref, onClickOutside) {
  useEffect(() => {
    /**
     * Invoke Function onClick outside of element
     */
    function handleClickOutside(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        onClickOutside();
      }
    }
    // Bind
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // dispose
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [ref, onClickOutside]);
}

执行你的法典:

const Home = () => {
  let [open, setOpen] = useState(false);
  const wrapperRef = useRef("menu");
  useClickOutside(wrapperRef, () => {
    setOpen(false);
  });

  return (
    <section>
      <h1>Feels good to be home!</h1>
      <div ref={wrapperRef}>
        <button className="secondary" onClick={() => setOpen(!open)}>
          Dropdown Toggle
        </button>

        {open && (
          <ul>
            <li>One</li>
            <li>Two</li>
          </ul>
        )}
      </div>
    </section>
  );
};

Another way to go about it in React is using a Callback and useEffect hooks: This example is for a mobile menu close on outside and it works the same with whichever element you want to close, simply add the ref={element} in order to trigger the close.

  const [toggleNav, setToggleNav] = useState(false);
  const mobileMenuRef = useRef();

  const closeOpenMenus = useCallback(
    (e) => {
      if (
        mobileMenuRef.current &&
        toggleNav &&
        !mobileMenuRef.current.contains(e.target)
      ) {
        setToggleNav(false);
      }
    },
    [toggleNav]
  );

  useEffect(() => {
    document.addEventListener("mousedown", closeOpenMenus);
  }, [closeOpenMenus]);

加入<条码> Mriganka Ghosh s response, there will be some cases when we 我想对外部边界增加例外。

我们可以这样做:

function useOutsideAlerter(
    ref: any,
    handleClick: () => void,
    exceptionElementsRef: React.MutableRefObject<any>[]
) {
   useEffect(() => {
      function handleClickOutside(event: any) {
           if (exceptionElementsRef.some((exceptionElement) => 
               exceptionElement.current.contains(event.target))
              ) return;

      if (ref.current && !ref.current.contains(event.target)) {
           handleClick();
      }
      }

      document.addEventListener("mousedown", handleClickOutside);
      return () => {
           document.removeEventListener("mousedown", handleClickOutside);
      };
    }, [ref]);
}

而且:

function OutsideClickHandler({ children, handleClick, exceptionElementsRef }: any) {
    const wrapperRef = useRef(null);
    useOutsideAlerter(wrapperRef, handleClick, exceptionElementsRef);

    return <div ref={wrapperRef}>{children}</div>;
}

P.S:为我的坏打字类型提供职业介绍。

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

export default function Page(){
  const [isOpen, setIsOpen] = useState(false)
  
  const btnRef = useRef()
  
  useEffect(() => {
        const closeDropdown = e => {
            if (!btnRef.current.contains(e.target)) {
                setIsOpen(false);
            }
        }
        document.body.addEventListener( click , closeDropdown)
        return () => document.body.removeEventListener( click , closeDropdown)
    }, [])
  
  return (
    <>
      <div ref={btnRef}>Open</div>
      { isOpen && (
        <div>
          Some block
        </div>
      )}
    </>
  )
}




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签