Oct 21, 2019

Explicando los beneficios de usar React Hooks como si tuvieras cinco años - con ejemplos


Desde que React.js llegó a la versión 16.8, introducen el uso de Hooks. Esta era la alternativa para mejorar los componentes funcionales y tener las mismas capacidades que los componentes de la clase, sobre lo que escribí hace un tiempo.

En primer lugar, ¿qué son los Hooks de React?

Los Hooks son una variedad de funciones, en su mayoría puras, agregadas a la API React que nos permiten usar toda la lógica con estado en los componentes funcionales sin cambiar su estructura.

El equipo de React explicó que encontraron varios problemas durante algunos años manteniendo diez de miles de componentes. Deciden crear una nueva forma de usar el estado y los ciclos de vida en los componentes. Puedes leer aquí la motivación.

Asi que, aquí le mostramos cómo comprender el concepto de Hooks. Veremos lo más relevante y cómo puede migrar fácilmente un componente de clase.

useState

Este es el Hook más común y comprensible, utilizado como homólogo de this.state con algunas diferencias leves. Podemos decir que useState es una función que recibe el estado inicial del componente y devuelve un arreglo con dos valores, el primero es el estado actual y el segundo la función "setState" de este estado.

Hemos creado un componente de un botón que cambia el color cada vez que hacemos clic en él. Veremos las dos formas, con clase y después con Hooks.

Componente de clase
// Class component

class ButtonRandomColor extends Component {

  constructor(props) {
    super(props)
    
    // inicializando el state en el constructor
    this.state = {
      currentColor: ""
    }
    // Apuntando la referencia de "this" a este componente.
    // con Hooks evitamos hacer esto.
    this.changeColor = this.changeColor.bind(this)
  }

  // Función para cambiar el color del estado
  changeColor() {
    const letters = '0123456789ABCDEF';
    let color = '#';
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    this.setState({
      currentColor: color
    }) ;
  }

  // Método de render
  render() {
    return (
      <button 
        onClick={this.changeColor}
        style={{
          backgroundColor: this.state.currentColor
        }}>
        Cambia mi color
      </button>
    )
  }
}
Componente funcional
function ButtonRandomColor () {
  const letters = '0123456789ABCDEF';
  // color es el estado actual y setColor es la función para cambiarlo. 
  // puede asignar el nombre que desee, esto es posible gracias a la desestructuración 
  // parte de las capacidades de ES5 de javascript.
  const [color, setColor] = React.useState("") 

  // Declaramos la función getRandomColor como una "arrow function".
  const getRandomColor = () => {
    let color = '#';
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color
  }

  // Esta es la plantilla que se renderizará.
  return (
      <button 
        onClick={() => setColor(getRandomColor()) }
        style={{
          backgroundColor: color
        }}>
        Cambia mi color
      </button>
  )
} 
Diferencias y beneficios con Hooks
  • No necesitamos usar el método del constructor entero.
  • El estado no es necesario que sea un objeto. Podría ser un valor primitivo. (string, number, boolean)
  • Ahorramos escritura sin usar "this"
  • Los alias de el nuevo state hacen que el código sea más legible.
  • Luce sintácticamente más simple.

useEffect

El Hook useEffect nos muestra cuán simple podría ser la vida sin los métodos del ciclo de vida. Le permite realizar efectos secundarios en los componentes de la función. Pero, ¿qué significa? Significa todas las operaciones que se ejecutan antes o después del proceso de representación.

Se usa comúnmente con solicitudes de API y procesos asincrónicos. Echemos un vistazo con un ejemplo.

Componente de clase
class LyricViewer extends Component {

  // inicializando el state en el constructor
  constructor(props) {
    super(props)
    this.state = {
      currentLyrics: ""
    }
    this.getLyric = this.getLyric.bind(this)
  }

  // Método para recuperar los datos y guardarlos en el estado.
  async getLyric() {
    const { author, song } = this.props
    const res = await fetch(`https://api.lyrics.ovh/v1/{author}/{song}`)
    const response = await res.json()
    this.setState({
      currentLyrics: response.lyrics
    })
  }

  // Recupera los datos cuando el componente esté montado.
  componentDidMount() {
    this.getLyric()
  }

  // Valida si los accesorios han cambiado para llamar al método componentDidUpdate. 
  // Ayuda a evitar solicitudes innecesarias
  componentShouldUpdate(nextProps) {
    const { author, song } = this.props
    if (nextProps.author === author && nextProps.song === song) {
      return false
    }
    return true
  }

  // Recupere los datos nuevamente si los accesorios cambian.
  componentDidUpdate() {
    this.getLyric()
  }

  // Renderiza las líricas
  render() {
    return (
      <div>
        {this.state.currentLyrics}
      </div>
    )
  }
}
Componente funcional
// Aquí, estamos usando la desestructuración para obtener
// justo lo que queremos del objeto props pasado como parámetro.
function LyricViewer ({ author, song }) {
  const [lyrics, setLyrics] = React.useState("")

  const  getLyric = async () => {
    const res = await fetch(`https://api.lyrics.ovh/v1/{author}/{song}`)
    const response = await res.json()
    setLyrics(response.lyrics)
  }

  // A continuación, la parte importante de este fragmento.
  // Esta función se llamará cuando se monte nuestro componente
  // y / o algunas de estas variables pasadas como segundo parámetro en el arreglo
  // cambia su valor.
  React.useEffect(() => {
    getLyric()
  },[author, song]) 
  // Si el valor de author o song cambia, useEffect se ejecutará nuevamente..

  // Plantilla
    return (
      <div>
        {lyrics}
      </div>
    )
} 
Diferencias y beneficios con Hooks
  • Reemplazamos tres métodos solo con una función.
  • Este enfoque simplifica el proceso de renderizado del componente.
  • useEffect se evalúa a sí mismo cuando debería actualizarse (no se necesita componentShouldUpdate).
  • Casi el 60% del código se ha reducido.
  • Prácticamente, los mismos beneficios del Hook pasado.

Otros Hooks

Con base en los hooks anteriores que cubrimos aquí, el equipo de React ha implementado para nosotros casi 8 hooks, no cavaremos en profundidad aquí, pero revisemos algunos de los más relevantes:

  • useContext: Recibe un Objeto Conext de React y devuelve el valor de contexto actual.
  • useReducer: Es muy similar a useState, pero usa un reducer (como Redux) y el estado inicial para devolver el estado actual y la función del despachador.
  • useCallback: Es útil cuando necesitamos memorizar operaciones de "alto peso". Devuelve el callback memorizado.
  • useRef: Devuelve un objeto mutable cuyo valor de propiedad actual se pasa como argumento.

Básicamente, estos hooks tienen un uso más avanzado y es posible que no se usen con frecuencia. Si desea leer más sobre consulte la documentación oficial de React.

Entonces, ¿Los Hooks valen la pena?

Totalmente sí, lo demostramos un poco más arriba. Al principio es un poco confuso olvidarse del esquema de "clase" pero le garantizo que al usarlos puede mejorar su productividad al escribirlos más fácilmente.

Este es el nuevo enfoque que está tomando React, pero no estamos obligados a migrar todas nuestras aplicaciones existentes a ganchos, por lo que es bueno usar estadísticas y preparar los nuevos proyectos para la innovación de la biblioteca.

Así que dime. ¿Ya usas Hooks? ¡Comenta abajo y comparte!

Explicando los beneficios de usar React Hooks como si tuvieras cinco años - con ejemplos
Commentarios