@HitGirl

Как изменить порядок вызова обработчиков событий?

В приведённом ниже примере сначала выполняется обработчик нажатия на кнопку (click в консоли), а затем уже обработчик клика вне элемента (outside в консоли). Можно ли как-то это исправить, чтобы outside всегда выполнялся до click?

import {FC, RefObject, useEffect, useRef, useState} from "react";

function useEventListener(event: string, callback: (e: any) => void, element: EventTarget = document) {
    const callbackRef = useRef(callback)

    useEffect(() => {
        callbackRef.current = callback
    }, [callback])

    useEffect(() => {
        const handler = (e:any) => callbackRef.current(e)
        element.addEventListener(event, handler)
        return () => {
            element.removeEventListener(event, handler)
        };
    }, [event, element])
}

export function useClickOutside(ref:RefObject<HTMLDivElement>,cb:(param:any)=>any){
    useEventListener(
        "click",
        e => {
            if (ref.current == null || ref.current.contains(e.target)) return

            cb(e)
        },
        document
    )
}

const UseClickOutsideExample:FC = ()=>{
    const [open, setOpen] = useState(false)
    const modalRef = useRef<HTMLDivElement>(null)

    useClickOutside(modalRef, () => {
        console.log('outside')
        if (open) setOpen(prev=>prev?false:prev)
    })

    return (
        <>
            <button onClick={() => {console.log('click');setOpen(true)}}>Open</button>
            <div
                ref={modalRef}
                style={{
                    display: open ? "block" : "none",
                    backgroundColor: "blue",
                    color: "white",
                    width: "100px",
                    height: "100px",
                    position: "absolute",
                    top: "calc(50% - 50px)",
                    left: "calc(50% - 50px)",
                }}
            >
                <span>Modal</span>
            </div>
        </>
    )
}

export default UseClickOutsideExample;
  • Вопрос задан
  • 115 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Смотрим, что умеет addEventListener:

useCapture

A boolean value indicating whether events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.

Соответственно, element.addEventListener(event, handler, true).
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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