Tengo un componente de entrada de búsqueda en React, que también tiene muchas opciones. Quiero que el cuadro de opciones aparezca cuando la entrada esté enfocada o mientras haya interacción en el cuadro. Este cuadro debería desaparecer cuando se enfoca algo fuera de cualquiera de las entradas de búsqueda del cuadro. Por lo tanto, se comporta como un comportamiento bastante estándar.
Hay un problema que no estoy seguro de cómo resolver. Algunas de las acciones dentro del cuadro de opciones hacen que se represente otro componente dentro del cuadro, por lo que se pierde el foco (el navegador enfoca el <body> ). Mi componente piensa que significa ocultar el cuadro de opciones.
Encontré una solución para eso: solo escondo el cuadro si el blur del contenedor fue causado por algo externo. Funciona correctamente en algunos casos. Pero hay un problema cuando, digamos, hay un botón que hace que el cuadro de opciones muestre otra cosa, haciendo que el botón desaparezca. El foco va al <body> y ya no puedo ocultar el cuadro de opciones sin enfocar manualmente la entrada de búsqueda y luego enfocarme.
¿Existen algunas técnicas para gestionar la visibilidad por foco real o pseudo? En un escenario perfecto, me gustaría evitar enfocar programáticamente mi elemento, por dos razones:
autofocus funcione correctamente. Para simplificar, eliminé los accesorios y elementos irrelevantes para la pregunta. Pero están sucediendo bastante cosas para el <OptionsBox /> .
Aquí está mi componente simplificado:
import { useState } from 'react'; import OptionsBox from './OptionsBox'; export default function Search() { const [value, setValue] = useState(''); const [showOptions, setShowOptions] = useState(false); return ( <div tabIndex={-1} onFocus={() => setShowOptions(true)} onBlur={event => { const isChildFocused = event.currentTarget.contains(event.relatedTarget); if (!isChildFocused) { setShowOptions(false); } }} > <input type="text" value={value} onChange={event => setValue(event.target.value)} /> {showOptions && ( <OptionsBox /> )} </div> ); }Traté de encontrar alguna solución para trabajar en este problema y lo encontré de esta manera (en el enlace).
Autofocus (depende del requisito).track the click event . Si está dentro, mantén el foco; de lo contrario, desenfoca el <OptionBox />ref a parentDiv y se lo pasó a <OptionBox/> para el seguimiento2 buttons para probar eventos de focus onClick1st onCLick para enfocar body2nd onClick para enfocar input dentro de <Parent/> / <OptionBox/>clickHandler para verificar, si el element en el que intenta enfocarse está dentro de parentDiv , si es así, mantenga el focus ; de lo contrario, blur y setState el Estado en false .No estoy seguro de la eficiencia de esta solución, pero puede intentarlo (si aún no lo ha probado), ya que depende totalmente del caso de uso.
Enlace: https://codesandbox.io/s/youthful-hypatia-4mu2x?file=/src/OptionBox.js