@JDMeezy

Почему обработчик реагирует на событие, случившееся до его установки?

Открываю модальное окно по нажатию на кнопку. При рендере модального окна, вешаю слушатель, который при клике за пределы модального окна, закрывает его.

У меня модальное окно не появляется, так как сразу срабатывает функция handleOutsideClick. Но почему она срабатывает, если я назначаю слушатель на клик после того, как уже модальное окно открылось? Почему он реагирует на клик, который был сделал до инициализации данного слушателя?

При добавлении задержки, данная проблема уходит.

import React, { useEffect, useRef } from 'react';
import ItemColor from './ItemColor';
import { useSelector } from 'react-redux';

function ModalColors({onClose,status}) {

    const root = useRef();

    const {colors} = useSelector((store) => store.timer);

    useEffect(() => {
        const handleOutsideClick = e => root.current.contains(e.target) || onClose();
        document.addEventListener('click', handleOutsideClick);
        return () => document.removeEventListener('click', handleOutsideClick);
      }, []);

    return (
            <div className="modalWrapper">
                <div className="modalBody"  ref={root}>
                    <h2>Choose a theme</h2>
                    <hr />
                    <div className="colors">
                        {
                            colors && colors.map((item)=>(
                                <ItemColor active={item.activeWork} key={item.id} bg={item.color} />
                            ))
                        }
                    </div>
                </div>
            </div>
    ); 

}

export default ModalColors;
  • Вопрос задан
  • 160 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Я так понимаю, вот она, причина, подъехала с версией 18.0.0:

Consistent useEffect timing: React now always synchronously flushes effect functions if the update was triggered during a discrete user input event such as a click or a keydown event.

Т.е., жмёте на кнопку, открывается окно, запускается эффект, устанавливается обработчик клика на document, дальше событие клика по кнопке продолжило всплывать и попало в только что установленный обработчик.

При добавлении задержки, данная проблема уходит

Можете ещё попробовать ловить событие в фазе погружения:

document.addEventListener('click', handleOutsideClick, true);
return () => document.removeEventListener('click', handleOutsideClick, true);
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы