React Components vs React Hooks

Lista de diferencias entre los Class Componentes y los Hooks de React

Image for post
Image for post

English version: https://medium.com/@ger86/react-components-vs-react-hooks-52932d4ab6db

Esta semana he estado profundizando en los React Hooks, esa nueva funcionalidad que tanto hype creó en su presentación y a la que no he podido dedicarle excesivo tiempo hasta ahora.

Si habéis estado criogenizados estos ultimos meses aquí podéis ver la charla donde fueron mostrados por primera vez por Dan Abramov:

¿Qué he hecho para probarlos?

Para comenzar a habituarme a trabajar con los React Hooks me he definido un proyecto con las siguientes características:

  • Inicio de sesión con Facebook
  • Llamadas a una Api externa (concretamente a https://reqres.in/api, todo un descubrimiento si queréis trastear con llamadas a una API 💯)
  • Gestión del estado mediante Redux
  • Formulario de creación y edición de entidades
  • Enrutado de la aplicación mediante React Router y protección de rutas privadas
  • Uso de styled components

Y lo he desarrollado de dos formas distintas:

  • Empleando Components, es decir, a la manera “antigua”
  • Empleando hooks allí donde he considerado interesante emplearlos y sustituyendo todas las clases por funciones aprovechando los hooks useEffect y useState .

Existe otra diferencia entre ambos desarrollos: para el primero configuré yo a pelo webpack al más puro estilo old skool mientras que para el segundo empleé la herramienta create react app con el fin de ver con cual de las dos formas me sentía más cómodo (me quedo con la segunda opción por la sencilla razón de que permite olvidarnos de toda la configuración inicial y la instalación de dependencias).

Además, este segundo proyecto lo he programado mediante Typescript con el fin de ver qué tal se lleva con los hooks y probarlo como alternativa a flow y a los Prop Types . En líneas generales la migración ha sido sencilla pese a haberme topado con algún que otro problema en el tipado como era de esperar. Sin embargo, la prevención de errores que proporciona hace que merezca mucho la pena plantearse esta herramienta para proyectos relativamente grandes.

Dicho esto, voy a hacer un breve resumen de esta primera experiencia seria trabajando con React Hooks enumerando los aspectos que más me han gustado y aquellos que me han resultado más complicados de asimilar.

Si preferís ver los proyectos podéis ir al final del artículo donde os he dejado sendos enlaces a los repositorios de cara a que podáis ver el código completo y así ver de primera mano las diferencias.

Lo que más me ha gustado de los React Hooks

🌀 Código más limpio

En mi opinión, lo más llamativo cuando comienzas a sustituir la clases por componentes funcionales basados en hooks es lo limpio y organizado que se ve el código. Tal y como se mostraba en el vídeo de presentación que os indicaba antes, las líneas comienzan a descender automágicamente y la funcionalidad queda agrupada y en orden, lo cual nos evita tener que recorrer el archivo saltando entre diversas partes.

De hecho éste es uno de los motivos que llevaron al equipo de React a desarrollar los hooks:

♻️ Reutilización

No se si es porque estaba especialmente motivado cuando me puse a implementar el proyecto con hooks pero la sensanción general es que favorecen mucho la reutilización de código.

Por ejemplo, mientras desarrollaba la sección del creación y edición de usuarios se me vinieron a la cabeza diversas formas de aprovechar el hook useReducer para mantener el estado del formulario. Una de ellas podéis verla implementada en el custom hook useApiCall encargado de gestionar todo el proceso de llamar a una API externa.

De hecho, me he llegado a replantear la necesidad de emplear Redux Thunk para realizar las llamadas a la API y tirar más por la línea que proponen otros desarrolladores basada en realizar las llamadas en el componente y tan sólo pasar el resultado a la acción a Redux.

En cualquier caso mi sensación es que se abre un mundo de posibilidades con esta nueva funcionalidad.

💫 useEffect

Para mí, uno de los hooks más potentes y útiles gracias a la simplificación que aporta a nuestro código. Podríamos decir que useEffect es un todo en uno que agrupa los siguientes life cycle events de las clases: componentDidMount , componentDidUnmount y componentDidUpdate .

De este modo, gracias a useEffect podemos centralizar en un único método toda la lógica que antes duplicábamos en en dichos eventos, pues el método que le pasemos se ejecutará siempre después de cada render del componente. Os aconsejo que leáis en detalle la documentación para ahondar en sus características ya que entre otras cosas también podremos:

  • Decidir si el efecto se ha de ejecutar en función de si ciertas props han cambiado.
  • Ejecutar una función a modo de cleanup antes de ejecutar el efecto.
  • O ejecutar el efecto tan sólo cuando el componente sea montado y desmontado.

👋 This

Una de las consecuencias derivadas que supone la integración de los hooks y el paso a componentes funcionales es el evitarnos tener que pelearnos con la variable this , algo que muchos desarrolladores, especialmente los más juniors agradecerán.

Es cierto que con la llegada del plugin de Babel @babel/plugin-proposal-class-properties este problema se reducía bastante pero, para que nos vamos a engañar, evitar tener que preocuparnos por el valor de this resulta muy cómodo cuando estamos desarrollando (pese a que en mi opinión, ganar en comodidad no debería evitarnos aprender cómo funciona y cual es su valor esperado según qué casos).

🤖 Multitud de ejemplos

Parece que la comunidad se ha animado bastante a publicar hooks y ya hay algunas páginas que recogen un catálogo de los más interesantes, como por ejemplo:

Os recomiendo que echéis un ojo porque os permitirá ver la forma en que otros desarrolladores los emplean, algo que siempre viene bien para aumentar nuestras capacidades.

💔 Lo que menos me ha gustado de los React Hooks

😫 Curva de aprendizaje

Y ahora pasemos a los aspectos negativos, que en mi opinión quedan compensados por los beneficios que obtenemos pero que considero necesario mencionar sobre todo si estáis comenzando a profundizar en este nuevo paradigma.

Porque realmente realizar el salto de programar con Class Components a hooks es, por encima de todo, un cambio de paradigma. Es cierto que al principio comenzaremos por preocuparnos de las cosas evidentes:

  • sustituir los eventos del ciclo de vida por useEffect
  • sustituir el objeto estado por el hook useState

Sin embargo sospecho que esto va un poco más allá y que detrás de este cambio se encuentra una nueva forma de entender los componentes y de trabajar con ellos ya que, como os comentaba en la sección anterior, conforme nos familiaricemos con ellos tenderemos a crear nuestros propios custom hooks y a buscarles usos que van más allá del simple cambio sintático. De hecho ya existen páginas donde se recopilan hooks creados por la comunidad y es cuestión de tiempo que las grandes librerías como React Router, Redux Forms o mísmamente Redux los adopten.

Por tanto, más que no gustarme, diría que cambiar a trabajar con hooks va a suponer un esfuerzo extra que deberemos asumir si queremos beneficiarnos de todos los aspectos positivos que traen consigo.

😱 Cuidado con useEffect

Y ya, abandonando la clase de filosofía, creo que uno de los problemas al emplear hooks es que hay que ser muy cuidadoso con el empleo de useEffect de cara a evitar ciclos infinitos derivados del siguiente caso:

En este caso, después del primer render se ejecutará la función del useEffect dentro de la cual se invoca el método setItem que modifica el estado mediante el hook useState lanzando un nuevo que render que seguirá el mismo proceso, terminando por provocar un bucle infinito.

Es decir, forzar un render dentro de useEffect provocará que se vuelva a ejecutar el efecto y así hasta el infinito y más allá.

Otro aspecto en el que deberemos fijarnos mucho es el paso de dependencias a los hooks useEffect , useCallback y useMemo ya que React nos exige la siguiente norma: todo aquello que vayamos a usar dentro de un hook que esté sujeto a cambio deberemos pasarlo como dependencia en el segundo argumento (incluso las funciones). Para ayudarnos a cumplir con esta regla, existe un plugin de eslint desarrollado por el propio equipo de React que verificará que no la estamos incumpliendo:

🤔 useState

Finalmente, también me gustaría llamar la atención sobre la forma en que funciona el hook useState ya que probablemente las primeras veces que lo empleéis lo hagáis esperando un resultado similar a setState pero no es exactamente así.

Imaginad que tenéis lo siguiente:

Cuando llegue el momento de actualizar uno de los campos del objeto person tenderemos a emplear setPerson del mismo modo que setState , es decir:

Esperando obtener como estado:

Sin embargo, lo que obtendremos es:

ya que el método setPerson pisa por completo el objeto. De ahí que desde la documentación de React nos recomienden recurrir al hook useReducer si nuestro estado se complica mucho (aunque ya existen hooks de terceros que permiten manejar el estado del mismo modo que hacíamos con setState ).

Repositorios

Y tal y como había dicho, os dejo sendos repositorios para que podáis descargarlos y ver más de cerca las diferencias.

Si vais justos de tiempo os recomiendo que miréis sobre todo el custom hook useApiCall que he desarrollado y la forma en que simplifica las llamadas a una API y la gestión del estado de la llamada por medio de useReducer.

Espero que os sirva!

¿Quieres recibir más artículos como este?

Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇

Written by

Entre paseo y paseo con Simba desarrollo en Symfony y React

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store