Así que estoy tratando de usar un detector de eventos que activará el identificador solo si se hizo clic en cualquier botón de cualquier tipo, independientemente del contexto por el momento.
export const useClickButtonOutside = (ref, handler) => { React.useEffect( () => { const listener = event => { // Do nothing if event is not a button if (!(event.target instanceof HTMLButtonElement)) { return; } handler(event); }; document.addEventListener('mousedown', listener); document.addEventListener('touchstart', listener, { passive: false }); return () => { document.removeEventListener('mousedown', listener); document.removeEventListener('touchstart', listener); }; }, [ref, handler] ); };El problema principal que es difícil de lograr es:
Para lograr esto, debe observar la ruta del evento, que contendrá todos los elementos donde se disparó el evento. Debe verificar si esta cadena contiene un elemento de botón, si lo tiene, luego maneje el evento.
export const useClickButtonOutside = (ref, handler) => { React.useEffect(() => { const listener = (event) => { // Do nothing if path contains a button let isButton = false; event.path.forEach((element) => { if (element.tagName === "BUTTON") { isButton = true; return; } }); if (!isButton) { return; } handler(event); }; document.addEventListener("mousedown", listener); document.addEventListener("touchstart", listener, { passive: false }); return () => { document.removeEventListener("mousedown", listener); document.removeEventListener("touchstart", listener); }; }, [ref, handler]); };¿Puedes explicar más sobre el segundo punto?
Sobre el primero, cuando hace clic en un botón que tiene un elemento dentro, puede recibir el elemento interior en lugar de un botón.
Por ejemplo:
document.querySelector('button').addEventListener('click', e => { console.log(e.target); }); <button> <span>Test</span> </button>Eso es porque en realidad hizo clic en el lapso en lugar del botón, el botón recibe el evento debido a la propagación del evento.
Para obtener el elemento puedes hacer esto:
document.querySelector('button').addEventListener('click', e => { console.log(e.target.closest('button')); }); <button> <span>Test</span> </button>