¿Cómo utilizar los High Order Component (HOC) ?

¿Cómo utilizar los High Order Component (HOC) ?
Juan Carlos G2020-08-18

Bienvenido viajero, espero que mi curso de React JS te este siendo de gran ayuda, hoy traigo un nuevo episodio donde te mostrare como utilizar los HOCs conocidos así por sus siglas en ingles Higher Order Component.

Como siempre lo haré a través de un ejemplo que espero ilustre correctamente el ¿Por qué y para qué de este tipo de componente?

  • Te invito a revisar el capítulo anterior donde te hable de la comunicación de componentes mediante API Context.

Bien, no olvides en suscribirte a mi canal en YouTube con lo cual apoyarás este curso.

 

📌 Suscríbete a mi canal y activa la campanita para que no te pierdas ningún video 🤘

 

¿Qué aprenderás de los HOCs?

  • ¿Qué son y para qué sirven?
  • Como declararlos.
  • Como envolver componentes mediante tu HOC.
  • Comunicación componente padre a hijo.
  • Comunicación componente hijo a padre.

 

 

Repositorio:

  • Puedes acceder al código descargando lo directamente aquí "hoc".
  • O puedes clonar el repositorio con los siguientes comandos, el código se encuentra en la rama "hoc".
git clone https://github.com/EWebik/react-js.git
git checkout hoc

 

¿Qué son los Higher Order Components HOCs en React?

Lo primero que debes saber es que los HOCs no forman parte de la API de React como tal, más bien, son una especie de patrón que es resultante de la misma lógica de componentes de la librería de React.

No obstante, te dejo una definición que te puede ayudar a comprender mejor qué son.

Técnicamente es una función con la capacidad de recibir un componente como entrada y regresar un componente nuevo como salida.

 

¿Para qué sirven los HOCs?

Utilizar HOCs es considerado una técnica avanzada de React, que permite reutilizar lógica y trasmitirla a nuestros componentes que conformen nuestro proyecto.

En pocas palabras mientras la mayoría de componentes convierten propiedades a interfaz de usuario:

Los HOCs transforman un componente en otro componente agregando información a sus propiedades.

Entonces, mediante un HOC podemos reutilizar lógica y transmitirla a los componentes que serán envueltos con nuestro HOC.

 

Librerías de terceros que utilizan HOC

Muchas librerías de terceros utilizan esta técnica, por ejemplo:

  • Redux
  • Relay

 

Aplicación de ejemplo: Crea un HOC y envolver un componente con el.

En esta clase vamos a crear nuestro primer HOC, y lo haremos creando la aplicación de la siguiente imagen.

 

Aplicación ejemplo de la utilización de HOCs

Donde:

  • Será capaz de calcular el impuesto a un pago o precio dado.
  • Nuestro HOC recibirá una configuración de entrada.
  • Internamente hará los cálculos y se las pasaremos al componente de salida mediante su propiedades.

No olvides en ver el vídeo para comprender mejor este post y para ver el paso a paso de la implementación de Higher Order Component.

 

¿Cómo crear un HOC?

Bien, te mencione que este tipo de componente es una función, así que para declararlo lo haremos de la siguiente manera.

const withImpuestos = (Component) =>{
        return class extends React.Component{
             render(){
                      return(
                            <Component />
                      )
             }
        }
}

En esencia:

  • Se declara como una función tipo flecha.
  • En el nombre se recomienda utilizar la palabra "with" seguido de la palabra que más represente la función que tendrá el HOC.
  • Dicha función retorna una clase anónima, la cual debe extender de React.Component.
  • Al regresar un componente de clase, este debe poseer un método render, tal y como hemos visto en otros tutoriales.
  • Nuestro método render regresará el Component que ha recibido como parámetro.

Y listo con todo esto ya has creado tu primer HOC.

 

Creando nuestro HOC completo

const withImpuestos = (Component) =>{
  return (config)=> class extends React.Component{
    state={
      sucursal: config.sucursal,
      pago: "$" + config.pago,
      impuesto: 
        "$" + (config.pago * config.impuesto) 
        + " al " + (config.impuesto*100) + "%",
      ganancia: "$" + (config.pago - (config.pago * config.impuesto))
    }

    calcularImpuesto = (pago)=>{
      this.setState({
        pago: "$" + pago,
        impuesto: 
          "$" + (pago * config.impuesto) 
          + " al " + (config.impuesto*100) + "%",
        ganancia: "$" + (pago - (pago * config.impuesto))
      })
    }

    render(){
      return(
        <Component
          sucursal={this.state.sucursal}
          pago={this.state.pago}
          impuesto={this.state.impuesto}
          ganancia={this.state.ganancia}
          calcularImpuesto={this.calcularImpuesto} />
      )
    }
  }
}

El código anterior:

  • En primer lugar modificamos el return, ahora regresa una función anónima, que a su vez, regresara un componente de clase.
  • Por otra parte, en nuestro componente de clase tenemos que declarar un state para poder actualizar las propiedades que enviaremos en el componente que vamos a regresar.
state={
      sucursal: config.sucursal,
      pago: "$" + config.pago,
      impuesto: 
        "$" + (config.pago * config.impuesto) 
        + " al " + (config.impuesto*100) + "%",
      ganancia: "$" + (config.pago - (config.pago * config.impuesto))
    }
  • También declaramos el método calcularImpuesto, el cual recibirá las actualizaciones desde el componente que vamos a envolver, para analizar el dato y actualizar el state.
    calcularImpuesto = (pago)=>{
      this.setState({
        pago: "$" + pago,
        impuesto: 
          "$" + (pago * config.impuesto) 
          + " al " + (config.impuesto*100) + "%",
        ganancia: "$" + (pago - (pago * config.impuesto))
      })
    }
  • Y finalmente en el método render regresamos el componente que envolvemos y le agregamos las propiedades que deseamos.
render(){
      return(
        <Component
          sucursal={this.state.sucursal}
          pago={this.state.pago}
          impuesto={this.state.impuesto}
          ganancia={this.state.ganancia}
          calcularImpuesto={this.calcularImpuesto} />
      )
    }

Excelente, hasta este punto ya tienes tu HOC completo y posee la lógica que deseas reutilizar cada vez que envuelvas a otro componente, ahora toca diseñar el componente que deseamos envolver.

 

Creando el componente a envolver por el HOC

En el siguiente componente diseñaremos la interfaz que vimos en la imagen de este ejemplo.

function App(props) {
  const {sucursal, pago, impuesto, ganancia, calcularImpuesto} = props;
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>Impuestos sucursal {sucursal}</h1>
        <input type="number" onChange={(e)=>{
            calcularImpuesto(e.target.value)
          }
        } />
        <p>{"Pago: " + pago}</p>
        <p>{"Impuesto: " + impuesto}</p>
        <p>{"Ganancia: " + ganancia}</p>
        <a
          className="App-link"
          href="https://ewebik.com"
          target="_blank"
          rel="noopener noreferrer"
        >
          Tutorial React JS EWebik
        </a>
      </header>
    </div>
  );
}

 

  • Donde por destructuración obtenemos las propiedades que agrega el HOC.
const {sucursal, pago, impuesto, ganancia, calcularImpuesto} = props;
  • Como vez en las propiedades viene el método calcularImpuesto, el cual se lo pasamos al onChange del input para recuperar lo que escriba el usuario.
<input type="number" onChange={(e)=>{
         calcularImpuesto(e.target.value)
     }
 } />
  • Y finalmente rendereamos las propiedades mediante una etiqueta "p".
<p>{"Pago: " + pago}</p>
<p>{"Impuesto: " + impuesto}</p>
<p>{"Ganancia: " + ganancia}</p>

 

Y listo ya tienes tu aplicación funcionando, cada vez que introduzcas un dato en el input, se calculara el impuesto y veras tu HOC en acción.

Recuerda que toda la explicación viene en el vídeo paso a paso y puedes clonar el repositorio para analizar el código.

Espero te haya sido útil y hayas comprendido el por qué y para qué utilizar Higher Order Component en React, nos vemos en el siguiente post.

 


Juan Carlos G

Electrónica y diseño web

Durante años he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera página de Google, y hoy quiero compartir contigo lo que se en tecnologías como Node JS, PHP, C# y Bases de datos, si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.

Puedes seguirme en mis redes