useRef
useRef
es un React Hook que te permite referenciar un valor que no es necesario para el renderizado.
const ref = useRef(initialValue)
Uso
Referenciar un valor con una referencia
Llame a useRef
en el nivel superior de su componente para declarar uno o más referencias.
import { useRef } from 'react';
function Stopwatch() {
const intervalRef = useRef(0);
// ...
useRef
devuelve una referencia al objeto con una sola propiedad actual
Establecida inicialmente con el Valor inicial que usted proporcionó.
En los siguientes renderizados, useRef
devolverá el mismo objeto. Puedes cambiar su propiedad actual
para almacenar información y leerla más tarde. Esto puede recordarte a estado, pero hay una diferencia importante.
El cambio de una referencia no provoca una nueva renderización. Esto significa que las referencias son perfectas para almacenar información que no afecta a la salida visual de su componente. Por ejemplo, si necesita almacenar un ID de intervalo y recuperarlo más tarde, puedes ponerlo en una referencia. Para actualizar el valor dentro de la referencia, es necesario cambiar manualmente supropiedad actual
:
function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}
Más tarde, puedes leer el ID de ese intervalo desde la referencia para poder llamar a borrar ese intervalo:
function handleStopClick() {
const intervalId = intervalRef.current;
clearInterval(intervalId);
}
Al utilizar una referencia, te aseguras de que:
- Puedes almacenar información entre renderizados (a diferencia de las variables regulares, que se reinician en cada renderizado).
- El cambio de la misma no desencadena un renderizado (a diferencia de las variables de estado, que desencadenan un renderizado).
- La información es local para cada copia de su componente (a diferencia de las variables externas, que son compartidas).
El cambio de una referencia no desencadena un renderizado, por lo que las referencias no son apropiadas para almacenar información que se quiere mostrar en la pantalla. Utiliza el estado para eso. Leer más sobre [elegir entre useRef
y useState
].(/learn/referencing-values-with-refs#differences-between-refs-and-state)
Ejemplo 1 de 2: Contador de clics
Este componente utiliza una referencia para llevar la cuenta de las veces que se ha pulsado el botón. Tenga en cuenta que está bien usar una referencia en lugar de un estado aquà porque el recuento de clics sólo se lee y se escribe en un controlador de eventos.
import { useRef } from 'react'; export default function Counter() { let ref = useRef(0); function handleClick() { ref.current = ref.current + 1; alert('You clicked ' + ref.current + ' times!'); } return ( <button onClick={handleClick}> Haz clic en mÃ! </button> ); }
Si muestra {ref.current}
en el JSX, el número no se actualizará al hacer clic. Esto se debe a que el establecimiento de ref.current
no desencadena un renderizado. La información que se utiliza para el renderizado debe ser el estado en su lugar.
Manipulación del DOM con una referencia
Es particularmente común utilizar una referencia para manipular el [DOM].(https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API) React tiene soporte incorporado para esto.
En primer lugar, declare una referencia al objeto con un valor inicial de null
:
import { useRef } from 'react';
function MyComponent() {
const inputRef = useRef(null);
// ...
Entonces pasa tu objeto de referencia como el atributo ref
al JSX del nodo DOM que quieres manipular:
// ...
return <input ref={inputRef} />;
Después de que React cree el nodo DOM y lo ponga en la pantalla, React establecerá la propiedad actual
de su objeto de referencia a ese nodo DOM. Ahora puedes acceder al nodo DOM de <input>
y llamar a métodos como focus()
:
function handleClick() {
inputRef.current.focus();
}
React devolverá la propiedad actual
a null
cuando el nodo sea eliminado de la pantalla.
Más información sobre lamanipulación del DOM con referencias.
Ejemplo 1 de 4: Enfocar una entrada de texto
En este ejemplo, al hacer clic en el botón se centrará la entrada:
import { useRef } from 'react'; export default function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <input ref={inputRef} /> <button onClick={handleClick}> Centrar la entrada </button> </> ); }
Evitar la recreación del contenido de las referencias
React guarda el valor inicial de la referencia una vez y lo ignora en los siguientes renderizados.
function Video() {
const playerRef = useRef(new VideoPlayer());
// ...
Aunque el resultado de new VideoPlayer()
sólo se utiliza para el renderizado inicial, todavÃa estás llamando a esta función en cada renderizado. Esto puede ser un desperdicio si está creando objetos costosos.
Para solucionarlo, puedes inicializar la referencia de esta manera:
function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...
Normalmente, no se permite escribir o leer ref.current
durante el renderizado. Sin embargo, está bien en este caso porque el resultado es siempre el mismo, y la condición sólo se ejecuta durante la inicialización por lo que es totalmente predecible.
Deep Dive
Cómo evitar la comprobación de nulos al inicializar useRef posteriormente
Cómo evitar la comprobación de nulos al inicializar useRef posteriormente
Si utilizas un comprobador de tipos y no quieres comprobar siempre la existencia de null
, puedes probar con un patrón como éste:
function Video() {
const playerRef = useRef(null);
function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}
// ...
AquÃ, el propio playerRef
es anulable. Sin embargo, deberÃas ser capaz de convencer a tu comprobador de tipos de que no hay ningún caso en el que getPlayer()
devuelva null
. Entonces usa getPlayer()
en tus manejadores de eventos.
Referencia
useRef(valorInicial)
Llame a useRef
en el nivel superior de su componente para declarar una referencia.
import { useRef } from 'react';
function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...
Ver ejemplos de valores de referencia y [manipulación de DOM].(#examples-dom)
Parámetros
ValorInicial
: El valor que quieres que tenga inicialmente la propiedadactual
del objeto de referencia. Puede ser un valor de cualquier tipo. Este argumento se ignora después del renderizado inicial.
Devuelve
useRef
devuelve un objeto con una sola propiedad:
actual
: Inicialmente, se establece en elValorInicial
que has pasado. Más tarde puedes establecerlo a otra cosa. Si pasas el objeto de referencia a React como un atributoreferencia
a un nodo JSX, React establecerá su propiedadcurrent
.
En los siguientes renderizados, useRef
devolverá el mismo objeto.
Advertencias
- Puedes mutar la propiedad
ref.current
. A diferencia del estado, es mutable. Sin embargo, si contiene un objeto que se utiliza para la representación (por ejemplo, un pedazo de su estado), entonces usted no debe mutar ese objeto. - Cuando cambias la propiedad
ref.current
, React no vuelve a renderizar tu componente. React no se da cuenta de cuándo la cambias porque una referencia es un objeto JavaScript plano. - No escriba ni lea
ref.current
durante el renderizado, excepto para la [inicialización].(#avoiding-recreating-the-ref-contents) Esto hace que el comportamiento de su componente sea impredecible. - En el modo estricto, React llamará a la función de tu componente dos veces para ayudarte a encontrar impurezas accidentales. Este es un comportamiento sólo de desarrollo y no afecta a la producción. Esto significa que cada objeto ref se creará dos veces, y una de las versiones se descartará. Si la función de su componente es pura (como deberÃa ser), esto no deberÃa afectar a la lógica de su componente.
Solución de problemas
No puedo obtener una referencia a un componente personalizado
Si intentas pasar una referencia
a tu propio componente de esta manera
const inputRef = useRef(null);
return <MyInput ref={inputRef} />;
Es posible que aparezca un error en la consola:
Por defecto, tus propios componentes no exponen las referencias a los nodos del DOM que hay dentro de ellos.
Para solucionarlo, busca el componente del que quieres obtener una referencia:
export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}
Y luego envolverlo en forwardRef
asÃ:
import { forwardRef } from 'react';
const MyInput = forwardRef(({ value, onChange }, ref) => {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
});
export default MyInput;
Entonces el componente padre puede obtener una referencia a él.
Más información sobre el acceso a los nodos DOM de otro componente.