单击外部组件时关闭弹出窗口

时间:2019-06-28 09:57:01

标签: javascript reactjs react-hooks

在写这篇文章之前,我看到了this post,但是我无法将所有代码链接到我的代码上。

这是我的切换组件:

<ToggleContent
          toggle={show => (
            <div>
              <button type="button" onClick={show} className={styles.acronym}>
                {acronym}
              </button>
            </div>
          )
          }
          content={show => (
            <LogoutCard onClick={show} acronym={acronym} name={name} />
          )}
        />

这是ToggleContent

的内部
function ToggleContent({ toggle, content }) {
  const [isShown, setIsShown] = useState(false);
  const hide = () => setIsShown(false);
  const show = () => setIsShown(!isShown);

  return (
    <Fragment>
      {toggle(show)}
      {isShown && content(hide)}
    </Fragment>
  );
}

这是道具content

中LogoutCard的包装
import React, { useRef, useEffect } from "react";

/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref) {
  /**
   * Alert if clicked on outside of element
   */
  function handleClickOutside(event) {
    if (ref.current && !ref.current.contains(event.target)) {
      alert("You clicked outside of me!");
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  });
}

/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);
  useOutsideAlerter(wrapperRef);

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

问题

问题是我能够打印警报,但由于无法传递show值而无法关闭弹出窗口,这是唯一允许关闭并关闭的窗口。打开小弹出窗口。

问题

如何关闭弹出窗口?

1 个答案:

答案 0 :(得分:1)

您需要传递一个话语名称onClick函数,以处理执行以根据需要关闭弹出窗口所需的逻辑。将逻辑简化为只抵消当前状态的toggle动作也足以管理弹出窗口的显示/隐藏行为。

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

/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref, onClick) {
  /**
   * Alert if clicked on outside of element
   */
  function handleClickOutside(event) {
    if (ref.current && !ref.current.contains(event.target)) {
      alert("You clicked outside of me!");
      onClick();
    }
  }

  useEffect(() => {
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [handleClickOutside]);
}

/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);

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

function ToggleContent({ toggle, content }) {
  const [isShown, setIsShown] = useState(false);

  const toggle = () => setIsShown(!isShown);

  const onClick = () => {
    toggle()
  }
  useOutsideAlerter(wrapperRef, onClick);

  return (
    <Fragment>
      {toggle(show)}
      {isShown && content()}
    </Fragment>
  );
}