Tengo varias filas, cada fila contiene dos entradas de texto y un botón. Cuando el usuario se enfoca en una de las entradas, se debe mostrar el botón. Cuando los elementos pierden el foco, el botón debería volverse invisible una vez más. Mi mejor intento:
const Input = ({inputRef}) => { return ( <> <h1>Input</h1> <input type="text" ref={inputRef}/> </> ) } export default () => { const firstRef = useRef(null); const secondRef = useRef(null); const it = useRef(null); const [editing, setEditing] = useState(false); function handleClick(e) { firstRef.current.focus(); } function handleSave() { console.log("saving!"); } function checkFocus(e) { if (!it.current.contains(document.activeElement)) { setEditing(false); } else { setEditing(true); } } useEffect(() => { document.body.addEventListener("focus", checkFocus, true); return () => { document.body.removeEventListener("focus", checkFocus, true); } }, []); return ( <div ref={it}> <Input inputRef={firstRef}/> <Input inputRef={secondRef}/> <button type="button" onClick={handleSave} style={{visibility: editing ? "visible" : "hidden"}}>Save</button> <button type="button" onClick={handleClick}>Edit</button> </div> ) }¿Hay alguna forma mejor/más elegante y eficiente de lograr esto?
Puede usar los eventos onBlur y onFocus .
Esto debería funcionar como se esperaba, solo adapte la lógica en su componente
EDITAR
Editado el método onBlur.
const INITIAL_STATE = { input: '' } export default function App() { const [show, setShow] = useState(false); const [value, setValue] = useState(INITIAL_STATE); const handleChange = (e) => { const { value, name } = e.target; setValue(prevState => ({ ...prevState, [name]: value })) } const onBlur = () => { if (!value.input) { setShow(false) } } return ( <> <Input name="input" onChange={handleChange} value={value.input} onFocus={() => setShow(true)} onBlur={onBlur} /> {show && <button>TEST</button>} </> ); } const Input = (props) => { return ( <> <h1>Input</h1> <input {...props} type="text" /> </> ); };Aquí hay una solución para lo que está intentando usando solo CSS, lo que en mi opinión lo hace más elegante (y un poco más eficaz, pero en realidad esto es insignificante).
https://codepen.io/danny_does_stuff/pen/QWMprMJ
<div> <input id="input1" /> <input id="input2" /> <button id="save-button">Save</button> <button id="edit-button">Edit</button> </div> <style> input#input2:focus + button#save-button { visibility: hidden; } </style>Si quisiera hacerlo de una manera más React, podría hacer lo que Marco B sugirió en su respuesta .