为什么react-select的菜单选择的setState使模式关闭状态?

时间:2019-11-20 12:29:39

标签: javascript reactjs react-select

我有一个模态,它监听模态的外部点击并触发onclose方法来关闭模态。现在,我向模态添加了react select,在选择了一个选项之后,它使模态进入关闭状态。 我正在从其中一篇文章中捕获外部点击。

function useOuterClickNotifier(onOuterClick, innerRef) {
  useEffect(() => {
    if (innerRef.current) {
      document.addEventListener("click", handleClick);
    }
    return () => document.removeEventListener("click", handleClick);

    function handleClick(e) {
      if (innerRef.current && !innerRef.current.contains(e.target)) {
        onOuterClick(e);
      }
    }
  }, [onOuterClick, innerRef]);
}

https://medium.com/@pitipatdop/little-neat-trick-to-capture-click-outside-with-react-hook-ba77c37c7e82

我的index.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import Select from "react-select";
import Modal from "../Modal";

const options = [
  { value: "chocolate", label: "Chocolate" },
  { value: "strawberry", label: "Strawberry" },
  { value: "vanilla", label: "Vanilla" }
];

function App() {
  const [isOpen, setOpen] = useState(false);
  function onCloseModal() {
    console.log("Why closing?");
    setOpen(false);
  }

  function openModal() {
    setOpen(true);
  }
  return (
    <>
      {isOpen && (
        <Modal closeModal={onCloseModal}>
          <div className="card">
            <Select options={options} />
          </div>
        </Modal>
      )}
      <button onClick={openModal}>Open modal</button>
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

我该如何解决?

https://codesandbox.io/s/usegooglemap-repro-x3q37?fontsize=14&hidenavigation=1&theme=dark

系统信息

System:
    OS: macOS 10.14.5
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
  Binaries:
    Node: 12.4.0 - ~/.nvm/versions/node/v12.4.0/bin/node
    Yarn: 1.16.0 - ~/.nvm/versions/node/v12.4.0/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v12.4.0/bin/npm
  Browsers:
    Chrome: 78.0.3904.97
    Firefox: 69.0
    Safari: 12.1.1
  npmPackages:
    react: 16.11.0 => 16.11.0 
    react-dom: 16.11.0 => 16.11.0 
    react-scripts: 3.2.0 => 3.2.0 

1 个答案:

答案 0 :(得分:2)

我相信这是由于调用挂钩的事件侦听器时选择菜单已被卸载而造成的。 React不知道手动附加的单击处理程序,因此它将立即开始更新DOM。到事件由您的侦听器处理时,单击的DOM节点已被删除。

为防止您可以将true作为第三个参数传递给addEventListenerremoveEventListener。此参数为useCapture。如果为true,它将在捕获阶段目标元素的任何监听器之前呼叫您的监听器。

From mdn

  

useCapture [可选]

     

一个布尔值,指示是否将此类事件调度到   已注册的listener,然后再分发给任何EventTarget   在DOM树下面。向上冒泡的事件   树不会触发指定使用捕获的侦听器。事件   冒泡和捕获是传播事件的两种方式   当一个元素嵌套在另一个元素中时   元素已注册该事件的句柄。事件   传播模式确定元素接收序列的顺序   事件。请参阅DOM 3级事件和JavaScript事件顺序以了解   详细说明。如果未指定,则useCapture默认为false

Edit useGoogleMap repro

function useOuterClickNotifier(onOuterClick, innerRef) {
  useEffect(() => {
    if (innerRef.current) {
      document.addEventListener("click", handleClick, true);
    }
    return () => document.removeEventListener("click", handleClick, true);

    function handleClick(e) {
      if (innerRef.current && !innerRef.current.contains(e.target)) {
        onOuterClick(e);
      }
    }
  }, [onOuterClick, innerRef]);
}