React Hooks:用于模式事件侦听器的useEffect

时间:2019-06-24 13:39:33

标签: javascript reactjs react-hooks use-effect

我有一个模态对话框,如果用户在模态之外单击,我想关闭它。我编写了以下useEffect代码,但遇到以下问题:

模式对话框包含许多子级(反应节点),这些子级可能会更改(例如,用户删除列表的条目)。这些交互触发了我的onClick方法,但是由于已从模式中删除了单击列表项,因此即使单击位于模式内,该模式也会关闭。

我认为在useEffect的第二个参数处添加[children]将足够快地清理旧的效果事件侦听器,以至于该方法不再再次运行,但事实并非如此。

我在状态为ignoreNextClick的类组件中处理了相同的问题,但是必须有更清洁的解决方案,对吧?

    useEffect( () => {
        const onClick = ( event ) => {
            const menu = document.getElementById( 'singleton-modal' );
            if ( !menu ) return;

            // do not close menu if user clicked inside
            const targetInMenu = menu.contains( event.target );
            const targetIsMenu = menu === event.target;
            if ( targetInMenu || targetIsMenu ) return;

            onCloseModal();
        };

        window.addEventListener( 'click', onClick, false );

        return () => window.removeEventListener( 'click', onClick, false );
    }, [ children ] );

2 个答案:

答案 0 :(得分:0)

您可以从event.target检查模态的父代。 如果当前目标在模态内,则return

您可以使用closest来做到这一点。

请参阅以下解决方案。

...

    if (event.target.closest( '.singleton-modal' ) || event.target.classList.contains('singleton-modal')) {
       return;
    }

...

答案 1 :(得分:0)

我找到了一种不需要任何形式的旧道具存放方式的解决方案。

useEffect调用如下所示:

useEffect( () => {
        const onClickOutside = () => onCloseModal();
        window.addEventListener( 'click', onClickOutside, false );
        return () => window.removeEventListener( 'click', onClickOutside );
    }, [] );

如果用户在模态中单击,则直接将以下Click侦听器添加到模式中将阻止调用窗口Click-Listener。

<div
    className={`modal ${ classes }`}
    onClick={event => event.stopPropagation()}
    role="presentation"
>
   {children}
</div>`

我还添加了角色介绍,以使模态更易于访问和符合咏叹调。