Poder hacer referencia de un elemento del DOM o de un componente de clase (class components porque tiene instancia)
📖 Documentación | 🎬 Como usar react refs _ Leo Medina |
- Controlar focus, selección de textos o reproducción de medios
- Integracion con bibliotecas DOM de terceros
El atributo ref es especial y solo se puede usar en componentes de clase y elementos del DOM
"React asignará a la propiedad current el elemento del DOM cuando el componente sea montado, y la asignará de nuevo null cuando sea desmontado. La referencia es actualizada antes de los métodos componentDidMount o componentDidUpdate"
No puedes hacer uso de referencias de componentes de función debido a que no tienen instancias.
- El método createRef devuelve un objeto que en la clave current tiene la referencia al elemento DOM
class CreateRef extends React.Component { /* Crea una referencia(crea un objeto) para guardar el elemento textInput del DOM */ inputRef = React.createRef(); ...
- Pasamos la referencia en el atributo ref del elemento que queremos
return ( <> <input type="text" ref={this.inputRef} /> </> );
- Podemos usar esa referencia en cualquier lugar de la clase y para hacer referencia al elemento DOM debemos acceder a la clave curent
class CreateRef extends React.Component { //... handleFocus = () => { if (this.inputRef) { console.log("Focus"); /* Estamos accediendo la propiedad "current" para obtener el nodo del DOM */ this.inputRef.current.focus(); } }; //... render() { return ( <> <h2> {/* ... */} <input type="text" ref={this.inputRef} /> <button onClick={this.handleFocus}>Focus</button> </h2> </> ); } }
Podemos hacer un ref a componentes de clase Personalizados y poder hacer uso de sus métodos en el padre.
- En el hijo tenemos el ref y el método que hacen focus
class CustomTextInput extends React.Component { /* Crea una referencia(crea un objeto) para guardar el elemento textInput del DOM */ inputRef = React.createRef(); handleFocus = () => { if (this.inputRef) { console.log("Focus"); /* Estamos accediendo la propiedad "current" para obtener el nodo del DOM */ this.inputRef.current.focus(); } }; render() { return ( <> <h2> <input type="text" ref={this.inputRef} /> </h2> </> ); } }
- Hacemos uso del método handleFocus en el padre para simular un click y que se haga focus al montar el componente
class CreateRefClassComponent extends React.Component { /* Crea una referencia(crea un objeto) para guardar la instancia del componente de clase la cual nos permitirá acceder a sus métodos*/ autofocusRef = React.createRef(); componentDidMount() { /* Podemos tener acceso a sus métodos que estan almacenados en la propiedad current */ this.autofocusRef.current.handleFocus(); } render() { return ( <> <CustomTextInput /> <CustomTextInput ref={this.autofocusRef} /> </> ); } }
React llamara al callback del ref con el elemento del DOM cuando el componente sea montado, y lo llamara con null cuando este se desmonte. Se asegura que las referencias serán actualizadas antes que el componentDidMount o el componentDidUpdate sean ejecutados.
- Pasamos una función al prop ref esta funcion recibirá al elemento como argumento
return ( <> <input type="text" ref={this.setInputTextRef} /> <button onClick={this.handleFocus}>focus</button> </> );
- almacenamos el elemento en una propiedad y podemos hacer uso de el en la clase
class CallbackRef extends React.Component { inputText = null; /* Esta funcion recibe como parámetro el elemento del DOM y podemos asignarlo a una propiedad*/ setInputTextRef = (element) => { this.inputText = element; }; handleFocus = () => { /* comprobamos que el elemento este montado en el DOM */ if (this.inputText) { console.log("focus"); this.inputText.focus(); } }; ... }
Se encuentra actualmente deprecado y no se debe de usar
Solo funciona en class components
- Agregamos una prop llamada ref con un string que viene a ser el nombre del ref que usaremos para acceder al elemento
return ( <> <input type="text" ref="nameRef" /> <button onClick={this.handleFocus}>focus</button> </> );
- Podemos hacer uso de métodos que existen en el elemento nativo
handleFocus = () => { console.log("click in focus"); console.log(this.refs.nameRef); this.refs.nameRef.focus(); };
Reenvio de ref es una característica opcional que permite pasar ref entre componentes
Solo funciona para componentes funcionales y a partir de react 16.3
- En el componente padre creamos la ref y la pasamos como parámetro ref al componente funcional hijo
const GrandParent = () => { /* Creamos la ref */ const nameRef = React.createRef(); return ( <div> {/* La pasamos al compoennte hijo */} <CustomComponent ref={nameRef} /> </div> ); };
- Envolvemos el componente hijo(componente funcional) con React.forwardRef el cual recibe una funcion que tiene como segundo parámetro el ref y la asignamos al elemento DOM o componente de clase que queremos referenciar.
const CustomComponent = React.forwardRef((props, ref) => { return ( <div> <input type="text" ref={ref} /> </div> ); });
Podemos pasar una prop con un nombre alternativo a ref
- Creamos la ref en el componente padre y la enviamos al hijo como una prop con un nombre diferente a ref
class GrandParent extends React.Component { constructor(props) { super(props); /* Creamos el ref */ this.nameRef = React.createRef(); } render() { /* LO enviamos en una prop */ return <Parent inputRef={this.nameRef} />; } }
- Asignamos la ref que pasamos al elemento o clase en su atributo ref
const CustomComponent = (props) => { return ( <div> {/* Asignamos la prop recibida */} <input type="text" ref={props.inputRef} /> </div> ); };
Podemos pasar una prop con un nombre alternativo a ref
- Creamos el callback en el componente padre y la enviamos al hijo como una prop con un nombre diferente a ref
class GrandParent extends React.Component { nameRef = null; callbackRef = (element) => { this.nameRef = element; }; render() { /* LO enviamos en una prop */ return <Parent inputRef={this.callbackRef} />; } }
- Asignamos la ref que pasamos al elemento o clase en su atributo ref
const CustomComponent = (props) => { return ( <div> {/* Asignamos la prop recibida */} <input type="text" ref={props.inputRef} /> </div> ); };