繁体   English   中英

反应 useEffect 和 mousedown 侦听器

[英]React useEffect and mousedown listener

我有一个模式,如果用户在它外面点击就会关闭。

方法一- 传递isModalOpened因此 state 只有在isModalOpened为真时才会在单击时更新。

const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);

const clickOut = (e) => {
  if (!ref.current.contains(e.target) && isModalOpened) {
     toggleModal(false);
  }
};

React.useEffect(() => {
  window.addEventListener('mousedown', clickOut);

  return () => {
     window.removeEventListener('mousedown', clickOut);
  };
}, [isModalOpened]);

方法二- 从 dep 数组中删除isModalOpened

const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);

const clickOut = (e) => {
  if (!ref.current.contains(e.target)) {
     toggleModal(false);
  }
};

React.useEffect(() => {
  window.addEventListener('mousedown', clickOut);

  return () => {
     window.removeEventListener('mousedown', clickOut);
  };
}, []);

问题:我应该传递还是不传递isModalOpened到 dep 数组?

你不需要它。

原因是如果您toggleModal为相同的false值,它不会导致重新渲染。

因此,您无需防范isModalOpened的值,这会导致您 function 中不包含该变量,从而导致根本不需要依赖项。

不,您不应该将isModalOpen传递给深层数组,因为在这种情况下,您的效果只会删除并再次添加侦听器。 没必要

方法一将在每次isModalOpened更改时运行挂钩,在模式关闭时删除全局侦听器。 方法二将在(未)挂载组件时运行挂钩,这意味着全局侦听器将在整个组件生命周期中处于活动状态。

答案取决于您打算如何使用该组件。 我猜你计划在模式打开之前安装组件(因此初始状态为false ),这意味着你的第二种方法将从组件安装到卸载的那一刻监听mousedown事件。 如果您计划仅在模式打开时安装组件,则此方法将有效。 但你不是,这意味着你应该只在模式打开时设置全局侦听器。

第一种方法是正确的。

*编辑

但是您可以在 if 语句中删除isModalOpened检查。

我建议对此采取一些不同的方法。 我会在这里将clickOut function 包装在useCallback中,它具有作为toggleModalref的依赖项,并将clickOut作为 useEffect 中的依赖useEffect 这样,每当您reftoggleModal更改时,您都会对 clickOut 有一个新的引用,如果您对clickOut有新的引用,您将在clickOut中再次分配监听useEffect 这将帮助您在每个渲染上创建不必要clickOut function 并优化渲染。

因此,根据我的建议,您的代码将如下所示:

const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);

const clickOut = useCallback((e) => {
  if (!ref.current.contains(e.target) && isModalOpened) {
     toggleModal(false);
  }
}, [isModalOpened, ref]);

React.useEffect(() => {
  window.addEventListener('mousedown', clickOut);

  return () => {
     window.removeEventListener('mousedown', clickOut);
  };
}, [clickOut]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM