El día 12 de Junio de este mismo año parte del equipo de frontend de Apiumhub tuvo la oportunidad de asistir a la conferencia de React Next 2019 en Tel aviv, una conferencia centrada principalmente en React y React Native. Una vez allí tuvimos la oportunidad de asistir a varias conferencias muy interesantes, algunas sobre frameworks de React, sobre la optimización y mejora de performance del código de React o sobre SEO con una SPA, de entre otras. La charla que más me llamó la atención fue “Modern React – The Essentials” de Liad Yosef, en la que explicó las últimas novedades de React, como React Hooks, concurrent mode, suspense, lazy.
Personalmente me interesó mucho el uso de React Hooks, y cómo estos podrían cambiar el desarrollo de React, por lo que pasaré a explicar los principales usos de estos.

 

React Hooks: cómo podrían cambiar el desarrollo de React

 

useState hook

Empezaremos viendo una clase tradicional de React, hemos creado un dropdown que está formado por un botón que ejecutará el toggle de estado para mostrar o ocultar nuestra lista de items:


  export default class Dropdown extends Component {
  constructor() {
    super();
    this.state = { isDropdownvVisible: false };
    this.handleClick = this.handleClick.bind(this);


  handleClick() {
    this.setState(() => {
      return { isDropdownvVisible: !this.state.isDropdownvVisible };
    });
  }


  render() {
    const { isDropdownvVisible } = this.state;
    return (
      <div>
        <button onClick={this.handleClick}>Toogle dropdown</button>
        { isDropdownvVisible &&
            <ul>
                <li>First item</li>
                <li>Second item</li>
                <li>Third item</li>
              </ul>

      </div>
    );
  };
}

sandbox

En el siguiente ejemplo podemos ver que al hacer click en el botón ejecutaremos la función “handleClick” que cambiará el valor de la variable de estado “isDropdownvVisible”, por lo que la lista de html reaccionará a esta cambio y mostrará u ocultará la lista en base al valor de dicha variable.

A pesar de que funcione correctamente podemos ver como tenemos que escribir mucho código para ejecutar un simple toogle de un booleano. Para solucionar esto, React nos ofrece la posibilidad de usar React Hooks.

Usar React hooks nos permite usar funciones y aún así seguir teniendo variables de estado, por lo que nos ahorramos toda la verbosidad que conlleva usar una clase.

Para ello vamos a usar la función `useState` de React.

import React, { useState } from "react";

Una vez importada, la usaremos de la siguiente manera:

const [isDropdownvVisible, toogleDropdownVisibility] = useState(false);

 

Primero definiremos un array que contiene dos variables:

  • Value: El nombre de la variable de estado que queremos definir. En nuestro caso se llamará “isDropdownVisible”.
  • ModifierFunction: El nombre de la función que modificará nuestro estado. En nuestro caso se llamará “toogleDropdownVisibility”.

Además dentro de la propia función `useState` podemos definir el valor inicial de nuestra variable. En nuestro caso empezará siendo false.

Reescribiendo el código anterior usando React hooks en vez de clases quedaría así:


export default function Dropdown() {
  const [isDropdownvVisible, toogleDropdownVisibility] = useState(false);

  function handleClick() {
    return toogleDropdownVisibility(!isDropdownvVisible)
  }
  
  return (
      <div>
        <button onClick={handleClick}>Toogle dropdown</button>
        { isDropdownvVisible &&
            <ul>
                <li>First item</li>
                <li>Second item</li>
                <li>Third item</li>
              </ul>

      </div>
    );
}

sandbox

 

Apium Academy

useEffect hook

Además de permitirnos tener estado sin obligarnos a usar clases, los React hooks nos ofrecen un sinfín de posibilidades, una de las más destacadas es la función `useEffect` que nos permite hacer side effects dentro de nuestra función.

Usando “useEffect” avisamos a React que queremos que la función que pasamos como parámetro se ha de ejecutar en cada render(por defecto), lo que nos ahorra depender de métodos del lifecycle como “componentDidUpdate”, “componentWillUnmount”, etc.

Veamos un ejemplo usando el componente que hemos definido anteriormente:


import React, { useEffect, useState } from "react";

export default function Dropdown() {
  const [isDropdownvVisible, toogleDropdownVisibility] = useState(false);

  function handleClick() {
    return toogleDropdownVisibility(!isDropdownvVisible)
  }

  useEffect(() => {
    console.log(isDropdownvVisible);
  })

    return (
      <div>
        <button onClick={handleClick}>Toogle dropdown</button>
        { isDropdownvVisible &&
            <ul>
                <li>First item</li>
                <li>Second item</li>
                <li>Third item</li>
              </ul>

      </div>
    );
}

Ejecutando el código anterior podemos ver cómo en cada render del componente nos mostrará el valor de la variable “isDropdownvVisible”.

En este caso no tendremos ningún problema, ya que es un simple loggeo de datos, pero qué pasaría si quisiéramos hacer una petición http cuando el valor cambie, tendríamos que hacerla en cada render?
Para evitar esto podemos pasarle un segundo parámetro a la función “useEffect” formado por un array con el valor que queremos comparar, y a menos que sea diferente, no se ejecutará la función que hemos definido como primer parámetro de “useEffect”.

  useEffect(() => {
    console.log(isDropdownvVisible);
  }, [true])

En este caso solo nos mostrará el valor cuando sea “false”.

Ya hemos visto cómo usar el hook de effects para poder encapsular nuestra lógica, por lo que podemos crear nuestros propios hooks para compartir funcionalidades entre diferentes componentes, como sería el caso de fetch de datos, parseo de datos, etc.
Esto nos permite crear nuestros servicios y compartirlos de forma muy rápida y limpia.

Como conclusión en cuanto al uso de React Hooks, nos ofrece un cambio radical en la creación de nuestros componentes y servicios, ya que pasamos de usar clases a poder usar funciones con estado interno y nos ahorramos todo el “boilerplate” de implementar todo el flujo del lifecycle de React usando `useEffect`, por lo que una vez comentadas estas mejoras sólo queda probar cómo adaptar nuestro código al uso de React Hooks y poder disfrutar de estos.