Tengo un contenedor que tiene dos elementos secundarios: un campo de entrada y otro elemento div que se representa condicionalmente según el valor de isActive . El problema con el que me encuentro es que cada vez que hago clic en el elemento div secundario, se activa onBlur .
¿Cómo puedo evitar que esto suceda? Ya probé e.stopPropagation() como puede ver a continuación. Además, intenté mover onBlur y onFocus al contenedor div , pero tampoco funcionó.
import React from "react"; import "./styles.css"; export default function App() { const [isActive, setIsActive] = React.useState(false); const handleClick = React.useCallback((e) => { e.stopPropagation(); // does not work }, []); return ( <div className="container" onFocus={() => setIsActive(true)} onBlur={() => setIsActive(false)} > <input /> {isActive && <div className="child" onClick={handleClick} />} </div> ); }El problema es que el controlador onBlur en el elemento de entrada se activa cada vez que el usuario hace clic fuera de él. Por lo tanto, usar el detector de eventos onBlur puede no ser la solución.
Si solo está interesado en mantener visible el div secundario cuando el usuario hace clic en él, propongo agregar un detector de eventos de clic al document , que cuando se llama, verifica si el objetivo del evento está dentro del div del contenedor (principal de la input y el elemento secundario). div ) y oculte el div secundario en consecuencia.
export default function App() { const [isActive, setIsActive] = useState(false); const container = useRef(); useEffect(() => { const handler = (event) => { if (!container.current.contains(event.target)) { setIsActive(false); } }; document.addEventListener("click", handler); return () => { document.removeEventListener("click", handler); }; }); return ( <div className="container" ref={ctn}> <input className="input" onFocus={() => setIsActive(true)} /> {isActive && <div className="child" />} </div> ); }Esta solución no funcionará si realmente le importa el estado de enfoque del elemento de entrada. El usuario puede mover el foco con la pestaña.
Puedes probar la solución aquí
Explicación
{isActive && <div className="child" onClick={handleClick} />} handleClick aquí no lo ayuda, porque nunca se activa debido a la nueva representación, por eso e.stopPropagation() no funciona para su caso.
Otro problema es onFocus y onBlur solo se aplican para el elemento activable , por lo que significa que estos eventos ocurren en el campo de input (no div ). Puede intentar reemplazar input con otro div para el experimento.
Entonces, ¿cómo hacer que div se convierta en un elemento activable? Bueno, simplemente coloca tabindex para div . Su código funcionará correctamente
El atributo global tabindex indica que su elemento puede enfocarse
<div className="container" tabindex="100" //add tabindex here onFocus={() => setIsActive(true)} onBlur={(e) => { const currentTarget = e.currentTarget; // Give browser time to focus the next element requestAnimationFrame(() => { // Check if the new focused element is a child of the original container if (!currentTarget.contains(document.activeElement)) { setIsActive(false); } }); }} > <input /> {isActive && <div className="child" />} </div>