No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Creando tu primer HOC

13/19
Recursos

Aportes 44

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Es un tema muy complejo, aún no se me ocurre nada para aplicarlo y así complicarme la vida jejejej :p

Acabo de terminar toda la escuela de frontend con React y vengo a repasar el tema de los HOC’s. La verdad no entendí nada la primera vez que pasé por aquí, pero ahora todo tiene sentido!!

Si no entendiste nada en ésta clase, no te desanimes, con la práctica lo entenderás.
y recuerda, ¡Nunnca pares de aprender!

Aqui dejo un codigo de ejemplo

function App(props) {
  return (
    <h1>!{props.saludo}, {props.nombre}¡</h1>
  );
}

function withSaludo(WrapperdComponent) {
  return function WrapperdComponentWithSaludo(saludo) {
    return function ComponenteDeVerdad (props) {
      return (
        <React.Fragment>
          <WrapperdComponent {...props} saludo={saludo}/>
          <p>Estamos acompañamdo al WrapperdComponent</p>
        </React.Fragment>
      );
    }
  }
}

const AppwithSaludo = withSaludo(App)
const AppwithSaludo2 =AppwithSaludo('Buenass');
const AppwithSaludo3 =AppwithSaludo('Buenass amigos');



ReactDOM.render(
  <React.Fragment>
    <AppwithSaludo2 nombre={"Alex"} />
    <AppwithSaludo3 nombre={"jose"} />
  </React.Fragment>,
  document.getElementById('root')
);

Esto me recuerda demasiado a los decoradores de Python (:

Clases que me ayudaron a enteder esta clase (HOC)

Es importante aprender este concepto ya que para aplicaciones escalables(grandes) utilizaremos Redux en un futuro y este concepto te sera de utilidad

  1. Closures en programacion funcional
    Ir a la clase
  2. Currying en Javascript programacion funcional
    Ir a la clase
  3. Introduccion a la HOF (higher order funcition en JS)
    Ir a la clase

si alguien necesita un repaso de hof. este dev tiene una forma interesante de explicar

https://www.youtube.com/watch?v=BMUiFMZr7vk&list=PL0zVEGEvSaeEd9hlmCXrk5yUyqUag-n84

Es una forma de herencia en componentes funcionales, la difefrencia al no usar children, es que un children lo redderizas dentro de otro contexto, en el caso de un compoente hoc cuando lo renderizar puedes usar los metodos del compoenente padre, ya que al final elhoc es un clousure

Enamorado de esta clase!! que increíble lo que se puede aprender en una tarde de domingo!

Los “High Order Components” (HOCs) son un patrón común en React que se utiliza para compartir código y lógica entre diferentes componentes. Un HOC es una función que toma un componente como argumento y devuelve un nuevo componente que tiene acceso a ciertas propiedades o métodos adicionales. Esto puede ser útil en casos donde tienes varios componentes que necesitan acceder a la misma información o comportamiento, ya que puedes crear un HOC que contenga esa lógica y luego utilizarlo en diferentes componentes.

Si alguien quiere hacer esto con TypeScript esta es la mejor forma que se me ocurre lo he hecho con genéricos para que se adapte a cualquier componente

  • Primero creamos el componente App que este no tiene ningún misterio solo pasarle el tipado como cualquier componente en TypeScript
type App2Props = {
  name?: string;
  greeting?: string;
}

function App2(props: App2Props) {
  return (
    <h1>{props.greeting}, {props.name}!</h1>
    );
}
  • Este sería el primer componente que creamos solo con un wrapper:
function withWhatever<T>(Component: ComponentType<T>) {
  return function ComponenteDeVerdad(hocProps: T) {
    return (
      <>
        	<Component {...hocProps}/>
        	<p>Estamos acompañando al wrapped component</p>
      	     </>
    );
  }
}

const AppWithWhatever = withWhatever(App2)
  • Y este con dos wrapper:
function withSaludo<T>(Component: ComponentType<T>) {
  return function WrappedComponentWithGreeting(greeting: string) {
    return function ComponenteDeVerdad(hocProps: T) {
      return (
        <>
         		<Component {...hocProps} greeting={greeting}/>
         		<p>Estamos acompañando al wrapped component</p>
                 </>
      );
    }
  }
}

const AppWithSaludo = withSaludo(App2)("Hola")
  • En el render es exactamente igual que en JavaScript:
ReactDOM.render(
  <React.StrictMode>
    	<AppWithWhatever name="Jairo" greeting="Hola"/>
    	<AppWithSaludo name="Jairo" />
    </React.StrictMode>,
  document.getElementById('root')
);

🤯 Se parecé a un Callback Hell 🤯🤯

Aplicando el curryng con arrow functions

const withSaludo1 = (WrappedComponent) => {
  // add something
  return (saludo) => {
    // adding saludo
    return (props) => (
      <>
        <WrappedComponent
          {...props}
          saludo={saludo}
        />
        <p>Estamos acompañando al WrappedComponent</p>
      </>
    )
  }
}
  1. Simplified
const withSaludoSimplified = (WrappedComponent) => (saludo) => (props) => (
      <>
        <WrappedComponent
          {...props}
          saludo={saludo}
        />
        <p>Estamos acompañando al WrappedComponent</p>
      </>
)

Commit de la clase, por si alguien quiere hechar un ojo directamente al codigo, es más facil cuando se ve de golpe el resultado y despues se analiza el funcionamiento.

https://github.com/NightDreams/curso-react-patrones-render/commit/2cdbc86246aaae9d940c6361a5960fe8835b02e4

Esta clase me encanto, no se pero esta genial!


function greeting(props) {
    return (<h1 className="block">Hi! {props.name} </h1>)
}


function withHi(WrappedComponent) {
    return function (Companion) {
        return function (props) {
            return (
                <React.Fragment>
                    <WrappedComponent {...props}/>
                    <Companion {...props}/>
                </React.Fragment>
            );
        }
    }

}

function CompanionComponent(props) {
    return (<h1 className="inline">I'm your companion, {props.name}</h1>)
}


const Hi = withHi(greeting)(CompanionComponent);


function App() {
    return (
        <div className="text-center text-white">
            <Hi name="Ricardo"/>
        </div>
    );
}

const root = document.getElementById('root');
ReactDOM.render(
    <App/>,
    root
);

Ah caray!!!

Currying sirve para descomponer funciones complejas en otras funciones más pequeñas donde cada función recibe un solo argumento

// Sin Currying
function sumThreeNumbers(a, b, c) {
        return a + b + c
}

console.log(sumThreeNumbers(1, 2, 3)) // 6

//con Currying

function sumThreeNumbers(a) {
        return function(b) {
                return function(c) {
                        return a + b + c
                }
        }
}

console.log(sumThreeNumbers(1)(2)(3)) // 6

Segun como yo lo entiendo con el HOC podemos llamar dos funciones a la misma vez, Las dos se encargan de hacer cosas diferente pero llega un tiempo en que debe de unirser para entregar un resultado en comun. Me equivoco?

o no lo entiendo o nose como aplicarlo a un proyecto propio ?

Despues de la primear visualización del video

Dejo un ejemplo de cómo creé mi primer HOC:
Primero que todo, generé un componente específico para mostrar un saludo al principio de mi ToDo App, llamado Greeting, Aquí pueden verlo:

El cual tiene un código pequeño que recibe algunas render props y unas render functions y las ejecuta según sea el caso, como pueden ver en su código:

Y su implementación en la app:

Entonces, quise crear un HOC que cambiase el color de las letras en cualquier componente, y en especifico, usarlo para cambiar el color de mi saludo, para eso creé un HOC llamado ChangeLettersColor, así:

De esta forma, mi HOC, necesita como argumentos un color y un Componente al cual le cambiará el color original de sus letras, se utiliza de la siguiente manera:


Y este es su resultado!:

Espero que les sirva como ejemplo de cómo utilizar este conocimiento para este o cualquier otro proyecto que estén realizando. Saludos!

Muy interesante como se va armando la lógica del componente (función) que recibe un componente y devuelve un nuevo componente

Creando tu primer HOC

Vamos a ver un ejemplo para entender que es un HOC.

Digamos que deseamos tener un componente en el cual deseemos insertar información de manera dinámica. Podemos hacerlo con las props por ejemplo:

import React from "react";
import { ReactDOM } from "react-dom";

const root = ReactDOM.createRoot(document.getElementById('root'));

function AppEjemplo(props) {
	return (
    <h1>¡{props.saludo}, {props.nombre}!</h1>
  );
}

root.render(
  <AppEjemplo saludo="Buenas" nombre="andru" />
);

Esto funciona, pero podemos hacer uso de los HOC, ya entenderemos para que. Por convención al crear nuestro HOC debemos empezar con with y luego le decimos que tipo de inyección le haremos nuestro componente.

// La gracia de estas funciones es que retornen otra función
function withLoQueSea() {
  return function ComponenteDeVerdad(props) {
    /* Obligatoriamente SIEMPRE el ultimo return de un HOC debe
    retornar un componente de React */
    return <h2>Buenas</h2>
  }
}

Lo que hacemos después es crear una variable en la cual almacenemos a nuestro componente AppEjemplo luego de que lo hayamos envuelto en nuestro HOC withLoQueSea.

const AppWithLoQueSea = withLoQueSea(AppEjemplo);

Lo que nos permite los HOC es hacer uso de los WrappedComponent que lo podemos utilizar dentro de nuestro componente de verdad.

function withLoQueSea(WrappedComponent) {
  return function ComponenteDeVerdad(props) {
    return (
      <React.Fragment>
        <WrappedComponent />
        <p>Estamos acompañando al WrappedComponent</p>
      </React.Fragment>
    )
  }
}

...
root.render(
  <AppWithLoQueSea saludo="Hey" nombre="Juanita" />
);

Si vemos el navegador vemos de que a pesar de que le pasamos las propiedades al componente no las renderizó y solo aparece el párrafo.

Lo que pasa es que no le estamos enviando ninguna propiedad, aquí veremos la importancia de que la última función retorne un componente, para enviar y recibir estas propiedades debemos hacerlo con el Spread Operator dentro de los parámetros del WrappedComponent.

function withLoQueSea(WrappedComponent) {
  return function ComponenteDeVerdad(props) {
    return (
      <React.Fragment>
        <WrappedComponent {...props} />
        <p>Estamos acompañando al WrappedComponent</p>
      </React.Fragment>
    )
  }
}
...

Si vemos ahora el navegador ya aparecerá renderizada las propiedades.

Esto no es lo único que nos permite nuestros HOC, podemos tener muchas más funciones hasta retornar nuestro componente de verdad, veamos un ejemplo:

function withSaludo(WrappedComponent) {
  // La propiedad saludo será otro requerimiento de nuestro HOC
  // Este parámetro lo recibiremos directamente de AppEjemplo
  return function WrappedComponentWithSaludo (saludo) {
    return function ComponenteDeVerdad(props) {
      return (
        <React.Fragment>
          <WrappedComponent {...props} saludo={saludo} />
          <p>Estamos acompañando al WrappedComponent</p>
        </React.Fragment>
      )
    }
  }
}

function AppEjemplo(props) {
  /* Aquí se inyecta la propiedad saludo a nuestro 
  WrappedComponentWithSaludo */
	return (
    <h1>¡{props.saludo}, {props.nombre}!</h1>
  );
}

/* Aquí enviaremos nuestro saludo para que lo renderice el 
WrappedComponent */
const AppWithSaludo = withSaludo(AppEjemplo)('Wenas'); // saludo

root.render(
  <AppWithSaludo nombre="Juanita" />
);

Y ya lo tendríamos en el navegador:

Podemos jugar mucho con esto y tenemos una cantidad casi ilimitada de opciones, por ejemplo, si cambiamos de orden los parámetros que esperan las funciones cambiaremos el orden en el que enviamos al información.
function withSaludo(saludo) {
  return function WrappedComponentWithSaludo (WrappedComponent) {
    return function ComponenteDeVerdad(props) {
      return (
        ...
      )
    }
  }
}

// Ahora enviamos al revés los parámetros
const AppWithSaludo = withSaludo('Wenas')(AppEjemplo);

Y todo esto podemos hacer con los HOC’s, podemos hacer lo que queramos con estos.

what a crazy video 🤯🤯🤯

Si ya viste patrones de diseño de POO esto sería algo “similar” al patrón Decorator.

Le sume nombre.

function withSaludo(EtiquetaHTMLComponen){
  return function saludoFunction(saludo){
    return function nombreFunction(nombre){
      return function ComponenteDeVerdad(){
        return (
          <React.Fragment>
            <EtiquetaHTMLComponen nombre={nombre} saludo={saludo}/>
            <p>Pasamos saludo en la segunda funcion</p>
            <p>Pasamos nombre en la tercera funcion</p>
          </React.Fragment>
        )
      }
    }
  }
}
const AppWthatever = withSaludo(App)('Hola')('Gaston');

Es un tema que se parece a la composicion funcional en matematicas, entonces pueden entenderlo tambien asi.

Para entender mejor este tema pueden revisar el concepto de Closures. Es de mucha ayuda para entender el porqué estas funciones “recuerdan” el valor con el que se le llamó a su padre.

Que buena clase, Todo quedo muy claro y bien explicado

Like si te gusta complicar las funciones aunque solo sea para para practicar tus super poderes

loooool

const App =({name, sur})=> <h1>hola {name} {sur}</h1>


ReactDOM.render(

  <App {...{name: "JuanDc", sur: "with objects"}} />, 

document.getElementById("root"));

podemos también pasar 2 o mas componentes a nuestro HOC

function App (props){
  return (
      <p>{props.saludo} {props.nombre}</p>
    )
}
function App2 (props){
  return (
    <p>soy {props.other}</p>
  )
}

function HOC (Component){
  return function (Other){
    return function (saludo){
      return function (props){
        return (
          <>
            <Component {...props} saludo={saludo} />
            <Other {...props} />
            <h2>soy un texto</h2>
          </>
        )
      }
    }
  }
}

const MyComponent = HOC(App)(App2)('hey')


ReactDOM.render(
    <MyComponent nombre={'juan!'} other={'cualquier otro componente'}/>, 
    document.getElementById('root')
);


en el navegador veríamos algo así:
.
.
hey juan!
soy cualquier otro componente
soy un texto

Ahora que estuve investigando sobre el Currying en JS, puedo decir que entiendo mejor el HOC, pero me gustaría tener más ejemplos de como poder usarlo, y también saber si es óptimo trabajar con ellos.
Se parece un poco al patrón builder.
Y para que? xD

Creando tu primer HOC

.
Primero creamos el componente App que más adelante lo vamos a pasar como argumento a nuestro HOC quien lo recibirá de parámetro con el nombre de WrappedComponent.
.
La propiedad saludo se recibirá por medio del HOC mientras que el nombre lo enviaremos como propiedad al momento de llamar el componente AppWithSaludo.
.

function App(props) {
  return (
    <h1>¡{props.saludo}, {props.nombre}!</h1>
  );
}

.
Lo que sigue es crear el HOC withSaludo quien recibe como parámetro al saludo y retorna una función WrappedComponentWithSaludo que a su vez recibe como parámetro al componente WrappedComponent y retorna finalmente al componente ComponenteDeVerdad, que no es más que el componente WrappedComponent pero le hemos inyectado la propiedad saludo además de encapsularlo en un React.Fragment junto a una etiqueta <p>.
.
Entonces desde donde queramos llamar al HOC creamos una constante AppWithSaludo que llamará al HOC pasándole como argumentos el saludo y el componente App en ese orden respectivamente.
.
El orden en que mandamos los argumentos depende del orden en el que se reciben los parámetros en el HOC.
.

function withSaludo(saludo) {
  return function WrappedComponentWithSaludo(WrappedComponent) {
    return function ComponenteDeVerdad(props) {
      return (
        <React.Fragment>
          <WrappedComponent {...props} saludo={saludo} />
          <p>Estamos acompañando al WrappedComponent</p>
        </React.Fragment>
      );
    }
  }
}

const AppWithSaludo = withSaludo('Wenas')(App);

.
Finalmente, ya teniendo al componente resultante del HOC lo podemos llamar desde la aplicación y como se menciona al principio, también le pasamos la propiedad nombre que es propia del componente.
.

ReactDOM.render(
  <AppWithSaludo nombre="Juanita" />,
  // <App saludo="Buenas" nombre="Nath" />,
  document.getElementById('root')
);
Es. programacion funcinonal

Increible, aprendi currying con la “competencia de platzi”, que además es gratuita, porque platzi no tiene un curso al respecto, pero no imagine en donde lo podría utilizar, solo lo usaba para comprimir modulos.

Ahora con esto puedo ver que se le puede otorgar a react una capacidad de reutilizar codigo brutal.

Otra cosa es que en mi terminal me estan saliendo una cantidad de errores asombrosa, warning y type invalid. De momento no tengo tiempo para arreglarlos pero parecen errores por que uso una version mas nueva que la del curso.

Que rapido que habla el profesor, eso me fastidia(en buen sentido), lo tuve que poner en 0.85 jaja

Tuve que ver la clase en 0.85 para escuchar y entender poco a poco jaja!! Buena clase👏👏👏

Muy interesante, pero** ¿En qué ayudaría aplicar esto en mis proyectos sera para una mejor estructura, buenas prácticas ó quizas el performance?** 🧐🤔

interesante… estan chetadas

const App =( {name, sur}={} )=> <h1>hola {name} {sur}</h1>

const hoc =(WC)=> (props)=> { return ( <>
    <WC {...{name: "JuanDc", sur: "with objects"}} />
    <h2> acompañando a wc </h2>
    </>
  )
}

const Wrapper = hoc(App);

ReactDOM.render(

  <Wrapper />,
  
document.getElementById("root"));