Estoy jugando con ganchos y estoy tratando de hacer lo siguiente:
import React, { useState, useRef } from 'react'; const EditableField = () => { const [isEditing, setEditing] = useState(false); const inputRef = useRef(); const toggleEditing = () => { setEditing(!isEditing); if (isEditing) { inputRef.current.focus(); } }; return ( <> {isExpanded && <input ref={inputRef} />} <button onClick={toggleEditing}>Edit</button> </> ); }; Esto va a fallar, porque current es nula, ya que el componente aún no se ha vuelto a procesar y el campo de entrada aún no se ha procesado (y, por lo tanto, aún no se puede enfocar).
¿Cuál es la manera correcta de hacer esto? Puedo usar el usePrevious propuesto en las preguntas frecuentes de React Hooks, pero parece una solución dolorosa.
¿Hay una manera diferente?
Puede usar el gancho useEffect para ejecutar una función después de cada procesamiento cuando cambia isEditing . En esta función, puede verificar si isEditing es true y enfocar la entrada.
Ejemplo
const { useState, useRef, useEffect } = React; const EditableField = () => { const [isEditing, setEditing] = useState(false); const toggleEditing = () => { setEditing(!isEditing); }; const inputRef = useRef(null); useEffect(() => { if (isEditing) { inputRef.current.focus(); } }, [isEditing]); return ( <div> {isEditing && <input ref={inputRef} />} <button onClick={toggleEditing}>Edit</button> </div> ); }; ReactDOM.render(<EditableField />, document.getElementById("root")); <script src="https://unpkg.com/react@16.7.0-alpha.2/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.2/umd/react-dom.production.min.js"></script> <div id="root"></div>Sé que la respuesta aceptada cubre el elemento solicitado en la pregunta anterior.
Pero como nota adicional, si está utilizando componentes funcionales, utilice React.forwardRef para pasar la referencia a los componentes secundarios. Definitivamente podría ser útil para alguien que se refiera a esta pregunta más adelante.
De una manera más limpia, puede escribir su componente secundario que acepta la ref como se indica a continuación:
const InputField = React.forwardRef((props, ref) => { return ( <div className={props.wrapperClassName}> <input type={props.type} placeholder={props.placeholder} className={props.className} name={props.name} id={props.id} ref={ref}/> </div> ) })O simplemente use este componente
import { FC, useEffect, useRef } from 'react' export const FocusedInput: FC<JSX.IntrinsicElements['input']> = (props) => { const inputRef = useRef<null | HTMLElement>(null) useEffect(() => { inputRef.current!.focus() }, []) return <input {...props} type="text" ref={inputRef as any} /> }