Estaba revisando la documentación de los ganchos cuando me encontré con useRef.
Mirando su ejemplo ...
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
… Parece que useRefse puede reemplazar con createRef.
function TextInputWithFocusButton() {
const inputRef = createRef(); // what's the diff?
const onButtonClick = () => {
// `current` points to the mounted text input element
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
¿Por qué necesito un gancho para árbitros? ¿Por qué useRefexiste?
fuente

useRef, publicado por uno de los desarrolladores de React. No es lo mismo que simplemente llamarcreateRef, yacreateRefque no es un gancho y no persiste ningún estado entre llamadas. La respuesta de Ryan Cogswell también tiene un buen ejemplo de las diferencias.tldr
A
refes un objeto JS simple{ current: <some value> }.React.createRef()es una fábrica que devuelve un árbitro{ current: null }, sin magia involucrada .
Es suficiente usaruseRef(initValue)también devuelve una referencia{ current: initValue }similar aReact.createRef(). Además , memoriza esta referencia para que sea persistente en múltiples representaciones en un componente de función .React.createRefen componentes de clase, ya que el objeto ref se asigna a una variable de instancia , por lo tanto, accesible en todo el componente y su ciclo de vida:this.myRef = React.createRef(); // stores ref in "mutable" this context (class)useRef(null)básicamente es equivalente auseState(React.createRef())[0]1 .1 Reemplazar
useRefconuseState+createRefEl siguiente tweet ha sido esclarecedor para mí:
Con los conocimientos de la
tldrsección, ahora podemos concluir más:El código anterior "abusa"
useStatepara conservar la referencia devueltaReact.createRef().[0]simplemente selecciona la parte del valor deuseState-[1]sería el definidor.useStateprovoca una repetición en contraste conuseRef. Más formalmente, React compara la referencia del objeto nuevo y antiguo parauseState, cuando se establece un nuevo valor a través de su método de establecimiento. Si mutamos el estado deuseStatedirectamente (opuesto a la invocación del establecedor), su comportamiento se vuelve más o menos equivalente auseRef, ya que ya no se activa ninguna repetición:// Example of mutaing object contained in useState directly const [ref] = useState({ current: null }) ref.current = 42; // doesn't cause re-renderNota: ¡No hagas esto! Utilice la
useRefAPI optimizada en lugar de reinventar la rueda. Lo anterior es para fines ilustrativos.fuente
Solo para resaltar un propósito:
createRefes tan simple comoreturn {current: null}. Es una forma de manejarref=prop de la manera más moderna y eso es todo (mientras que la función de cadena es demasiado mágica y la devolución de llamada parece demasiado detallada).useRefmantiene algunos datos antes del renderizado y cambiarlos no provoca que se vuelva a renderizar (como louseStatehace). Rara vez están relacionados. Todo lo que espera para el componente basado en clases va a los campos de instancia (this.* =) parece candidato para ser implementadouseRefen componentes funcionales.Say
useCallbackfunciona como métodos de clase acotada (this.handleClick = .....bind(this)) y puede volver a implementarse (pero no deberíamos reinventar la rueda con seguridad)useRef.Otros ejemplos son las referencias DOM, los ID de tiempo de espera / intervalo, los identificadores o referencias de cualquier biblioteca de terceros.
PD: Creo que el equipo de React eligió un nombre diferente para
useRefevitar confusionescreateRef. QuizásuseAndKeepo inclusousePermanent.fuente
Sin embargo, otra adición importante a las respuestas de otros.
No puede establecer un nuevo valor para
createRef. Pero puedes poruseRef.const ur = useRef(); const cr = createRef(); ur.current = 10; // you can do it, and value is set cr.current = 10; // you can, but it's no good, it will not change itfuente
currentpropiedad como de costumbre (solo lo probé). No importa si la referencia se crea medianteuseRefocreateRef.