【问题标题】:Closing popup on clicking outside component单击外部组件时关闭弹出窗口
【发布时间】:2019-11-10 06:53:57
【问题描述】:

在写这篇文章之前,我看到了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>
  );
}

这是 LogoutCard 在 props content 中的包装

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 值,这是唯一允许关闭和打开的小弹出窗口。

问题

如何关闭弹出窗口?

【问题讨论】:

  • 如果你能把它放在 jsFiddle 或 codeSandbox 之类的东西里会很好。

标签: javascript reactjs react-hooks


【解决方案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>
  );
}

【讨论】:

  • 只是一个听起来很愚蠢的问题,但考虑到这是我作为 Web 开发人员的第二个月:我可以使用函数 `useOutsideAlerter(wrapperRef, onClick); ` 通过只导入组件 OutsideAlerter(logoutCard 的包装器)?
  • 没有。此外,您应该将其导入应该执行的位置。在您的情况下,适合的地方是 ToggleContent 组件。 OutsideAlerter 是您通过 content 属性在 ToggleContent 中渲染的函数。
猜你喜欢
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多