【Traducido】5 Principios Importantes de React Hooks
- 1238Palabras
- 6Minutos
- 27 Jul, 2024
Hoy en día, React sigue siendo una de las opciones más populares para crear aplicaciones frontend. Esto no es porque no tenga desventajas, sino porque React ha acumulado una enorme comunidad y popularidad a lo largo de los años.
Es difícil imaginar React sin hooks, pero desafortunadamente, a menudo vemos a los desarrolladores usándolos en exceso. Como resultado, se enfrentan a problemas con las dependencias, renders innecesarios y todo el caos que estos causan, ya que temen que en React, solo se puede hacer todo usando hooks.
En este artículo, discutiré cinco principios que todo nuevo programador de React debería conocer para mejorar y simplificar su código.
1. No cada función tiene que ser un Hook
Comencemos con lo básico, revisemos la definición.
Los hooks usan funciones JavaScript, pero representan una lógica de UI reutilizable especial y tienen restricciones en el lugar de llamada. Cuando uses hooks, debes seguir las reglas de los hooks.
Los hooks parecen funciones, pero hay algunas diferencias:
- Los hooks solo se pueden usar en componentes de función o en hooks personalizados.
- El nombre de un hook siempre comienza con “use” seguido de una letra mayúscula.
- Si un hook personalizado no contiene llamadas a otros hooks dentro, es solo una función, no un hook. Esto es importante porque ayuda a determinar si hay alguna lógica de estado o efectos secundarios en él.
Creemos un hook personalizado simple llamado useBoolean
que cumpla con estos requisitos. Podemos usarlo para abrir/cerrar paneles, diálogos, mostrar/ocultar elementos, etc.
Si revisas la documentación oficial, encontrarás que se recomienda envolver cualquier función devuelta por un hook en useCallback
, y también haremos eso.
1interface ICallbacks {2 setFalse: () => void;3 setTrue: () => void;4 toggle: () => void;5}6
7const useBoolean = (initialValue: boolean): [boolean, ICallbacks] => {8 const [value, setValue] = useState(initialValue);9
10 const setFalse = useCallback(() => {11 setValue(false);12 }, []);13
14 const setTrue = useCallback(() => {15 setValue(true);16 }, []);17
18 const toggle = useCallback(() => {19 setValue((curValue) => !curValue);20 }, []);21
22 return [value, { setFalse, setTrue, toggle }];23};
Después de recordar los fundamentos, podemos profundizar en algunos matices.
2. Entender el renderizado
Te podrías preguntar por qué.
Es importante entender cómo funciona React y qué sucede cuando cambias el estado de un componente a través de una función setter. A primera vista, parece que cambias el estado y el resultado debería aparecer de inmediato, ¿pero es así?
Cuando entiendes qué sucede al cambiar el estado, es más fácil comprender por qué y cuándo se activan useEffect
u otros hooks con arrays de dependencias.
Veamos un ejemplo simple. Imagina que presionamos un botón por primera vez y llamamos a onChangeText
, pasando el valor “newValue”.
1const [text, setText] = useState("defaultValue");2
3const onChangeText = (value: string) => {4 // value es igual a "newValue"5 setText(value);6
7 console.log(text); // ¿Qué valor aparecerá aquí?8};
Parece que deberíamos ver “newValue” en la consola, pero en realidad veremos “defaultValue”. ¿Por qué? Porque el nuevo valor solo estará disponible después del renderizado.
Es necesario ver los pasos que ocurren:
- Cambiamos el estado a través de una función setter, indicando a React que tome acción.
- Renderizado. React llama a tu componente para calcular el nuevo JSX que se devolverá.
- Compromiso. Después de calcular los cambios, React modificará el DOM; se aplicarán las acciones mínimas.
- Después de los pasos anteriores, verás el cambio visual en la pantalla (“renderizado en el navegador”).
Cada vez que quieras cambiar un valor en el estado, recuerda que estos pasos se completan cada vez.
3. useState no siempre es la respuesta correcta
En React, tenemos dos formas de manejar el estado de un componente: useState
y useReducer
. El segundo método no es tan popular porque se aplica a objetos más complejos en el estado y, para ser honesto, puede parecer demasiado complicado a primera vista para los nuevos programadores, pero no lo es.
Sin embargo, useState
parece muy simple y entendible, por lo que los nuevos programadores tienden a usarlo más de lo necesario.
Está diseñado para manejar el estado que vuelve a renderizar el componente en función de la interacción del usuario. Si deseas recordar algo sin renderizar, probablemente no deberías ponerlo en el estado. useRef
podría ser una mejor opción.
Si:
- Quieres recordar algunos valores durante el renderizado sin mostrárselos al usuario.
- Ya tienes datos en el estado, o los recibes a través de props, pero necesitas transformarlos; no necesitas guardar el nuevo valor en un nuevo objeto
useState
, crea una nueva variable y manipúlala sin activar renderizados innecesarios.
Necesitas guardar el valor en el estado si:
- Quieres volver a renderizar el componente cuando el valor cambia; los ejemplos más comunes son mostrar/ocultar paneles, spinners, mensajes de error y modificar arrays.
Simplifica tu código de esta manera:
1/**2El siguiente código causa renders innecesarios y uso innecesario de useEffect.3Cuando name o description cambian, React vuelve a renderizar el componente.4**/5
6const [name, setName] = useState("name");7const { description, index } = props;8const [fullName, setFullName] = useState("");9
10useEffect(() => {11 setFullName(`${name} - ${description}`);12}, [name, description]);
Cámbialo a:
1/**2Podemos usar el comportamiento predeterminado de React para obtener el valor correcto3cuando name o description cambian, sin activar un renderizado adicional.4**/5const [name, setName] = useState();6const { description, index } = props;7const nameWithDescription = `${name} - ${description}`;
4. Ten mucho cuidado al usar useEffect
useEffect
es un Hook de React que te permite sincronizar un componente con sistemas externos.
Veamos la documentación oficial:
Pero en realidad, usamos useEffect
mucho más de lo necesario. Es muy adecuado para obtener datos cuando se monta el componente, pero desafortunadamente, los nuevos programadores tienden a usar este Hook para cambiar el estado, lo que no es la mejor solución.
Si te encuentras escribiendo un useEffect
tras otro dentro de un componente, detente a revisar tu código. Normalmente no los necesitas y puedes eliminarlos rápidamente.
No necesitas useEffect
si:
- Necesitas manejar eventos del usuario (click); si sabes qué acciones desencadenan cierta lógica, no uses
useEffect
para llamar a esa lógica. - Necesitas transformar datos para renderizar, por ejemplo, conectar cadenas desde el estado o props. Colocar valores o lógica reactiva en el array de dependencias puede causar que
useEffect
se llame con demasiada frecuencia, provocando bucles infinitos.
Necesitas elegir useEffect
si:
- Quieres obtener datos cuando el componente se monta, establecer intervalos y usarlo para sincronizar el estado con otros sistemas.
5. No temas a useRef
Desafortunadamente, useRef
está subestimado. No es uno de los hooks más populares, pero es muy útil. Saber cómo y dónde usarlo puede ser muy beneficioso.
Comencemos con lo básico.
useRef
es un Hook de React que te permite hacer referencia a valores que no necesitan renderizarse. — De la documentación oficial de React.
Ya sea que estés creando un objeto de JavaScript para referenciar un nodo en el DOM o un valor simple, React recordará el valor que creaste con useRef
y no se perderá durante los renderizados.
¿Qué nos proporciona?
- Podemos acceder fácilmente a los elementos en el DOM. Por ejemplo, puedes obtener el valor de un campo de entrada, enfocar un elemento específico, obtener su altura y ancho, desplazarte a una parte específica de la pantalla, etc.
- Puedes recordar cualquier dato que necesites sin volver a renderizar el componente. Por ejemplo, si necesitas un contador o un temporizador, elige
useRef
en lugar deuseState
.
Ejemplo:
1// Referencia a un número2const refCount = useRef(0);3// Referencia a un campo de entrada4const refInputField = useRef(null);5
6/**7Para acceder a este valor, necesitas usar la propiedad current.8useRef no activará renderizados, por lo que puedes usarlo dentro de useEffect9sin preocuparte por el array de dependencias.10*/11
12const onClick = () => {13 refCount.current = refCount.current + 1;14 refInputField.current.focus();15}16
17return (18 <>19 <button onClick={onClick}>20 ¡Haz clic en mí!21 </button>22 <input ref={refInputField}></input>23 </>24);