Cómo usar componentes de orden superior para reutilizar la lógica en React

React logo sobre un fondo oscuro

Los componentes de orden superior (HOC) son un tipo de componente de React que le ayuda a reutilizar la lógica en su aplicación. La terminología puede parecer compleja, pero los HOC son fáciles de administrar y pueden simplificar el mantenimiento de la base del código.

UN Componente de orden superior siempre envuelve los componentes secundarios con funcionalidad adicional. Un HOC se define como una función que toma un componente como parámetro. Luego devuelve un archivo nuevo componente, que normalmente hará que el componente de entrada esté envuelto con accesorios adicionales.

→ Índice de contenidos

Un simple ejemplo

La mejor manera de apreciar cuando los HOC tienen sentido es verlos en acción. Consideremos un sistema de pago simple donde el estado del carrito del usuario se almacena de forma centralizada dentro de la aplicación. Nuestros ejemplos muestran Redux como un archivo estatal, pero solo con fines ilustrativos.

Supongamos que este objeto representa el estado de nuestra aplicación:

{
    checkout: {
        items: [
            {
                label: "Product 1",
                price: 150.00,
                quantity: 2
            },
            {
                label: "Product 2",
                price: 75.00,
                quantity: 1
            }
        ]
    }
}

Tenemos una matriz simple que representa los artículos en el carrito del usuario. Nuestros componentes de pago extraerán valores adicionales de este estado, como el valor total del pedido y los impuestos aplicables.

Nuestro sistema de pago probablemente tendrá que mostrar el valor total dentro de múltiples componentes independientes. Puede haber un widget de barra lateral que muestre el carrito, una pantalla de revisión posterior al pago y una calculadora de costos de envío. Un sistema ingenuo que simplemente pasara los artículos de pago como accesorios correría el riesgo de duplicar la lógica: cada componente tendría que calcular el valor total del pedido por sí mismo.

Presentación de HOC

Echemos un vistazo a cómo puede ayudar un HOC:

import React from "react";
import {connect} from "react-redux";
 
const withCheckout = ComponentToWrap => {
 
    const ComponentWithCheckout = class extends React.Component {
 
        render() {
            return (
                <ComponentToWrap
                    checkoutItems={this.props.checkout.items}
                    checkoutTotal={this.total}
                    {...this.props} />
            );
        }
 
        get total() {
            const prices = this.props.checkout.items.map(i => (i.quantity * i.price));
            return prices.reduce((a, b) => (a + b), 0);
        }
 
    }
 
    return connect(({checkout}) => ({checkout}))(ComponentWithCheckout);
 
}
 
export default withCheckout;

El archivo exporta una sola función, withCheckout, que toma un componente React como único parámetro (ComponentToWrap). Dentro de la función, creamos una nueva clase anónima que es en sí misma un componente de React.

Este nuevo componente es render el método crea una instancia de ComponentToWrap pasamos a la función. Ahora tenemos la oportunidad de definir los accesorios de la instancia. Reenviamos el conjunto de elementos de pago como checkoutItems y hacer que el valor total precalculado esté disponible como checkoutTotal.

Todos los accesorios que se pasan al HOC se envían al componente interno, lo que garantiza que reciba todos los datos necesarios. La función devuelve la clase anónima recién creada que está lista para ser renderizada en toda la aplicación.

Usamos el connect método de react-redux entonces el checkout prop dentro del HOC recibe el valor de checkout clave en el estado de nuestra tienda Redux. Este es un detalle de implementación: su HOC puede mantener su estado o comunicarse con otro servicio dentro de la aplicación.

Usando el HOC

Ahora es el momento de utilizar nuestro HOC.

import React from "react";
import withCheckout from "./withCheckout.js";
 
class CheckoutReviewScreen extends React.Component {
 
    render() {
        return (
            <h1>Checkout</h1>
            <h2>{this.props.checkoutTotal}</h2>
        );
    }
 
}
 
export default withCheckout(CheckoutReviewScreen);

Asumimos lo nuestro withCheckout HOC se guarda en withCheckout.js en el mismo directorio que nuestro nuevo componente de pantalla de pago. Envolviendo el componente con nuestro withCheckout HOC, podemos acceder y ver el valor total del pedido. No necesitamos calcularlo nosotros mismos ni almacenarlo en el estado de la aplicación. Si alguna vez queremos actualizar cómo se calcula el total (por ejemplo, para agregar una tarifa de manejo fija), solo necesitamos hacer el cambio en un lugar, dentro de nuestro HOC.

Ahora puedes renderizar <CheckoutReviewScreen /> en cualquier lugar de su aplicación. Nuestro ejemplo empaquetado no necesita recibir ningún apoyo, ya que obtiene sus datos de nuestra tienda Redux. Porque esta envuelto con withCheckout, envuelto a su vez con Redux's connect, la pantalla de revisión recibe automáticamente un archivo checkoutTotal prop que suma los precios de todos los artículos en el estado de la aplicación.

Ahora vale la pena mencionar lo que llamamos nuestro HOC: withCheckout. Por convención, los nombres HOC suelen tener una extensión with prefijo porque agregan algo a los componentes que envuelven. En nuestro caso, el HOC proporciona un acceso conveniente a nuestro carrito de pago que, de lo contrario, necesitaríamos implementar dentro de cada componente.

Ventajas de los HOC

El uso de un HOC le permite abstraer comportamientos comunes de los componentes, minimizando la duplicación de código y aumentando la capacidad de mantenimiento. Los HOC permiten una forma de inyección de dependencia. Le ayudan a mantener sus componentes más simples al permitir el paso de otros componentes del mundo exterior.

Los HOC son comunes dentro del ecosistema React. De hecho, vimos uno en este artículo: connect(), parte de react-redux, que suscribe sus componentes a los cambios de estado de Redux.

Los HOC son populares porque proporcionan un método de reutilización de código que no rompe la autocontención de los componentes. El patrón utiliza la capacidad de composición de React para permitirle agregar funcionalidad adicional sin el riesgo de efectos secundarios.

Puede pasar cualquier componente de su aplicación a withCheckout sin romper nada: el HOC solo ataca unos pocos accesorios extra. Por eso es tan importante que sus HOC reenvíen todas los accesorios que reciben{...this.props} en nuestro ejemplo). No deben hacer nada que pueda interferir con el funcionamiento normal del componente envuelto.

Puede parecer que sus componentes ahora dependen de su HOC. Este no es el caso. Puede exportar una segunda versión del componente que no está empaquetado, dando a los consumidores la opción de cuál usar.

Su componente en realidad solo insiste en recibir ciertos accesorios: checkoutTotal Yo nuestro caso. Esto podría ser proporcionado por el HOC o pasando un valor dondequiera que se represente el componente. Nuestro HOC simplifica el desarrollo, pero no ha cambiado fundamentalmente la naturaleza de nuestros componentes renderizados.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir Change privacy settings