useImperativeHandle
useImperativeHandle
es un Hook de React que te permite personalizar el identificador expuesto como una ref.
useImperativeHandle(ref, createHandle, dependencies?)
Referencia
useImperativeHandle(ref, createHandle, dependencies?)
Llama a useImperativeHandle
en el nivel superior de tu componente para personalizar el identificador ref que se expone:
import { forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... tus métodos ...
};
}, []);
// ...
Parámetros
-
ref
: Laref
que recibes como segundo argumento de la función renderforwardRef
-
createHandle
: Una función que no toma argumentos y devuelve el identificador ref que quieres exponer. El identificador ref que devuelve puede tener cualquier tipo. Por lo general, devolverá un objeto con lo métodos que quieres exponer. -
opcional
dependencies
: La lista de todos los valores reactivos a los que se hace referencia dentro del código decreateHandle
. Los valores reactivos incluye props, estados, y todas las variables y funciones declaradas directamente dentro del cuerpo de tu componente. Si tu linter es configurado por React, va a verificar que cada valor reactivo esté correctamente especificado como una dependencia. La lista de dependencias deben tener un número constante de elementos y ser escritos en una sola linea como[dep1, dep2, dep3]
. React comparará cada dependencia con su valor anterior usando el algoritmo de comparaciónObject.is
. Si un nuevo renderizado resultara en un cambio a una dependencia, o si no especificaste las dependencias completamente, tu funcióncreateHandle
se volverá a ejecutar, y el nuevo identificador recién creado será asignado a ref.
Devuelve
useImperativeHandle
devuelve undefined
.
Uso
Exponer un identificador ref personalizado al componente padre
Los componentes por defecto no exponen sus nodos DOM a los componentes padre. Por ejemplo, si quieres el componente padre de MyInput
para tener acceso al nodo DOM de <input>
, tienes que optar por forwardRef
:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});
Con el código de arriba, una ref a MyInput
va a recibir el nodo DOM de <input>
. Aun así, puedes exponer un valor personalizado en su lugar. Para personalizar el identificador expuesto, llama a useImperativeHandle
en el nivel superior de tu componente:
import { forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... tus métodos ...
};
}, []);
return <input {...props} />;
});
Ten en cuenta que en el código de arriba, la ref
ya no se reenvía a <input>
.
Por ejemplo, supongamos que no quieres exponer el nodo DOM entero de <input>
, pero quieres exponer dos de sus métodos: focus
y scrollIntoView
. Para hacer esto, mantén el DOM real del navegador en una ref separada. Entonces usa useImperativeHandle
para exponer un identificador solamente con los métodos que quieres que el componente padre llame:
import { forwardRef, useRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input {...props} ref={inputRef} />;
});
Ahora, si el componente padre obtiene una ref a MyInput
, podrá llamar a los métodos focus
y scrollIntoView
en él. Sin embargo, no va a tener acceso completo al nodo DOM de <input>
de manera más profunda.
import { useRef } from 'react'; import MyInput from './MyInput.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); //Esto no funcionará porque el nodo DOM no está expuesto // ref.current.style.opacity = 0.5; } return ( <form> <MyInput placeholder="Enter your name" ref={ref} /> <button type="button" onClick={handleClick}> Editar </button> </form> ); }
Exponer tus propios métodos imperativos
Los métodos que expones a través de un identificador imperativo no tienen que coincidir exactamente a los métodos del DOM. Por ejemplo, el componente Post
en el ejemplo de abajo expone a scrollAndFocusAddComment
por medio de un identificador imperativo. Esto le permite a la Página
padre desplazar la lista de comentarios y enfocar el campo de entrada cuando haces click al botón.
import { useRef } from 'react'; import Post from './Post.js'; export default function Page() { const postRef = useRef(null); function handleClick() { postRef.current.scrollAndFocusAddComment(); } return ( <> <button onClick={handleClick}> Escribe un comentario </button> <Post ref={postRef} /> </> ); }