在 React 组件中添加和删除监听器

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

我正在尝试在打开和关闭组件时添加和删除寡妇事件侦听器。

问题是处理程序中的

isOpen

 始终处于初始状态并且不使用最新状态。我该如何解决这个问题?我见过很多使用 
useEffect(() => { .. }, []);
 的解决方案,但这行不通,因为我希望能够在安装和卸载时的不同时间添加和删除侦听器。

我也尝试过使用

useCallback

,但它有与
useEffect
相同的问题

这是我当前的代码:

import { forwardRef, Ref, useEffect, useImperativeHandle, useRef } from 'react'; import { useState } from 'react'; type Props = { }; export const Popover = forwardRef((props: Props, ref: Ref<any>) => { const [isOpen, setIsOpen] = useState(false); const [clickOutsideHandler] = useState(() => (evt: MouseEvent): void => { console.log('!isOpen: ' + isOpen); // <-- issue is that `isOpen` is always false if (!isOpen || popoverRef.current.contains(evt.target as Node)) { return; } // Clicked on one of the own children close(); } ); const popoverRef = useRef(null); const open = (): void => { if (isOpen) { return; } setIsOpen(true); } const close = (): void => { if (!isOpen) { return; } setIsOpen(false); } useImperativeHandle(ref, () => ({ open, })); useEffect(() => { if (isOpen) { window.requestAnimationFrame(() => { // Wait 1 tick; otherwise a potential click that opend the element will immediately trigger a click-outside event document.addEventListener('click', clickOutsideHandler); }); } else { document.removeEventListener('click', clickOutsideHandler); } }, [isOpen]); return ( <> {(isOpen) && <div ref={popoverRef}> <div onClick={() => { close(); }}>Some Content here</div> </div> } </> ); });
问题是:如何使处理程序保留,同时仍然能够访问其中的正确状态?

reactjs react-hooks addeventlistener
1个回答
0
投票
您将

clickOutsideHandler

 函数定义为 
useState
,您应该将其设为实际函数,因为它不使用任何状态逻辑。


我会把它改成这样(没有 ts)

const clickOutsideHandler = (evt) => { if (!isOpen || popoverRef.current.contains(evt.target as Node)) { return; } // Clicked on one of the own children close(); };
    
© www.soinside.com 2019 - 2024. All rights reserved.