Es un tema muy complejo, aún no se me ocurre nada para aplicarlo y así complicarme la vida jejejej :p
Introducción
Qué son los patrones de render
Filosofía y principios de diseño en React
Composición de componentes
Qué es composición de componentes y colocación del estado
Composición y colocación del estado en React
Analizando la composición de Todo Machine
Composición de componentes con React Context
Composición de componentes sin React Context
Render props
Qué son las render props y render functions
Poniendo en práctica las render props
Súper poderes para render props y render functions
React.Children y React.cloneElement
High Order Components
Qué son los High Order Components
Creando tu primer HOC
Notificando cambios con StorageEventListener
Completando el StorageEventListener
Resolviendo los retos de StorageEventListener
React Hooks
Render props vs. High Order Components vs. React Hooks
Cambiando HOCs por React Hooks
Próximos pasos
Toma el Curso de React.js: Manejo Profesional del Estado
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Juan David Castro Gallego
Aportes 44
Preguntas 6
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 (:
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
type App2Props = {
name?: string;
greeting?: string;
}
function App2(props: App2Props) {
return (
<h1>{props.greeting}, {props.name}!</h1>
);
}
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)
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")
ReactDOM.render(
<React.StrictMode>
<AppWithWhatever name="Jairo" greeting="Hola"/>
<AppWithSaludo name="Jairo" />
</React.StrictMode>,
document.getElementById('root')
);
🤯 Se parecé a un Callback Hell 🤯🤯
const withSaludo1 = (WrappedComponent) => {
// add something
return (saludo) => {
// adding saludo
return (props) => (
<>
<WrappedComponent
{...props}
saludo={saludo}
/>
<p>Estamos acompañando al WrappedComponent</p>
</>
)
}
}
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.
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
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
.
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')
);
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"));
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?