点击外部的全局事件处理程序可防止触发反应事件

问题描述 投票:0回答:1

我已经实现了click-outside挂钩来关闭文档上mousedown上的菜单组件:

const useClickOutside = onClickOutside => {
  const ref = useRef(null);
  useEffect(
    () => {
      const handleClickOutside = e => {
        if (ref.current && !ref.current.contains(e.target)) {
          onClickOutside(e);
        }
      };
      document.addEventListener("mousedown", handleClickOutside);
      return () => {
        document.removeEventListener("mousedown", handleClickOutside);
      };
    },
    [onClickOutside, ref]
  );
  return ref;
};

菜单有一个输入,附加一个onBlur事件处理程序:

const Input = ({ onValueEnter }) => {
  const [value, setValue] = useState("");
  const handleValueChange = e => setValue(e.target.value);
  const handleBlur = () => onValueEnter(value);

  return (
   <input onBlur={handleBlur} value={value} onChange={handleValueChange} />
  );
};

const Menu = ({ onClose }) => {
  const ref = useClickOutside(onClose);
  return (
    <div ref={ref} className="menu">
      <h1>Enter value</h1>
      <Input onValueEnter={handleValueEnter} />
    </div>
  );
};

问题是输入中的onBlur事件永远不会触发,如果我在输入内有焦点并在菜单外单击。 Codesandbox的例子就在这里。

显然,因为react通过将事件附加到顶层而不是实际的dom节点来实现其自己的事件委托系统,所以全局事件处理程序(如在document.addEventListener中注册的那些)在react事件处理程序(github issue)之前运行。

所以我的问题是,如何解决这个问题?是否有可能以某种方式使onBlur事件处理程序先运行然后运行全局事件处理程序?

编辑:我已经在setTimeout中使用onClose的hack来暂时使其工作但我真的想避免它并找到更好的解决方案。

reactjs dom-events react-dom
1个回答
0
投票

我把一些东西混在一起让它起作用。它围绕使用forwardRef和imperativeHandle来关闭时从子访问值。我不知道这是否能解决你的问题。

https://codesandbox.io/embed/zw7jjopqq4

© www.soinside.com 2019 - 2024. All rights reserved.