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: Larefque 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óncreateHandlese 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 label="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} /> </> ); }