En aplicaciones pequeñas si muere, pero cuando trabajamos en un proyecto grande si requerimos de todos los poderes jeje
Tengo un proyecto personal en el que había atomizado y encapsulado todo de tal manera que cada archivo .js hacia solo una cosa y llamaba solamente a sus hijos (lo cual me da mucha seguridad al querer cambiar un comportamiento o interacción). Pero sentía que no me quedaba algo "DECLARATIVO".
Usando composición de componentes cambió el proyecto completamente!!!!
Mi sensación: antes ver mi código era como "leer un libro que tenía una palabra por página y había que dar la vuelta a la hoja a cada rato", muy incomodo y sin flow. Ahora parece una página de wikipedia que describe globalmente mi aplicación y con los enlaces para seguir profundizando (los imports) 😅😅😅😅
Ahora sí siento más declarativo a mi react. Gracias Juan
¡Yei! ¡Qué maravilla! Me alegra muchísimo que te haya ayudado la composición de componentes. :green_heart:
uff totalmente, que buen ejemplo el de la wikipedia, me paso lo mismo con un proyecto en js modular, como que no aprovechaba bien lo de ser modular, apenas aqui estoy entendiendo como funciona
Así vamos hasta este punto 🥶
Todo-Machine
Cosillas nuevas:
ID únicos para las tareas
Modo dark y light
UI creo que agradable y minimalista
Algo de responsive
Cualquier comentario y/o consejo bienvenido 😁
Cosa bella. Cosa hermosa. Cosa bien hecha.
Full de acuerdo, está muy chévere 👍
Ahora entiendo porque la propiedad children era su favorita :v
Nos lo habia advertido desde el primer curso jajaja
SIiiiiiii ajsaksjaksj
El curso de introducción me explotó la cabeza, mis proyectos en react eran un desastre no podía ni darle mantenimiento yo mismo, gracias al curso de introducción un proyecto de mi trabajo quedó súper bien y ahora con composición me siento más confiado y seguro de lo que hago, eres un gran maestro Juan!. Sigue así nunca pares de enseñar. :D
Genio!!!
que gran noticia bro.
Muchas gracias, me siento mucho más seguro con React.
El curso de introducción me dejo con cierta incertidumbre sobre como escalaria el proyecto solamente con props, pero esto de la composición es sin duda un salva vidas! Gracias David!
La composición de componentes es genial 😎
Composición de componentes sin React Context
Gracias a que no tenemos una aplicación que sea demasiado grande, podemos prescindir de usar React.useContext() usando la composición de componentes.
// Estos son los imports con los que funciona la aplicaciónimport{TodoCounter}from'../Components/TodoCounter/TodoCounter';import{TodoSearch}from'../Components/TodoSearch/TodoSearch';import{TodoList}from'../Components/TodoList/TodoList';import{TodoItem}from"../Components/TodoItem/TodoItem";import{TodoForm}from"../Components/TodoForm/TodoForm";import{CreateTodoButton}from'../Components/CreateTodoButton/CreateTodoButton';import{Modal}from"../Components/Modal/Modal";...functionAppUI(){/* Como vemos aquí AppUI es el unico componente que hace un llamado
al React.context() */const{ error, loading, searchedTodos, completeTodo, deleteTodo, openModal, setOpenModal, totalTodos, completedTodos, searchValue, setSearchValue
}=React.useContext(TodoContext);...}
TOOOOODA esta información la vamos a pasar directamente a nuestro componente App.js.
Para esto eliminamos el return del App.js y eliminamos estos imports:
Nos vamos a traer todo lo que está dentro de nuestro AppUI.js y lo vamos a pegar en nuestro App.js:
importReactfrom'react';import{TodoCounter}from'../Components/TodoCounter/TodoCounter';import{TodoSearch}from'../Components/TodoSearch/TodoSearch';import{TodoList}from'../Components/TodoList/TodoList';import{TodoItem}from"../Components/TodoItem/TodoItem";import{TodoForm}from"../Components/TodoForm/TodoForm";import{CreateTodoButton}from'../Components/CreateTodoButton/CreateTodoButton';import{Modal}from"../Components/Modal/Modal";functionApp(){const{ error, loading, searchedTodos, completeTodo, deleteTodo, openModal, setOpenModal, totalTodos, completedTodos, searchValue, setSearchValue
}=React.useContext(TodoContext);return(<React.Fragment><TodoCountertotalTodos={totalTodos}completedTodos={completedTodos}/><TodoSearchsearchValue={searchValue}setSearchValue={setSearchValue}/><TodoList>{error &&<p>Desespérate, hubo un error...</p>}{loading &&<p>Estamos cargando, no desesperes...</p>}{(!loading &&!searchedTodos.length)&&<p>¡Crea tu primer TODO!</p>}{searchedTodos.map(todo=>(<TodoItemkey={todo.text}text={todo.text}completed={todo.completed}onComplete={()=>completeTodo(todo.text)}onDelete={()=>deleteTodo(todo.text)}/>))}</TodoList>{!!openModal &&(<Modal><TodoForm/></Modal>)}<CreateTodoButtonsetOpenModal={setOpenModal}/></React.Fragment>);;}exportdefaultApp;
Gracias a esto podemos directamente eliminar AppUi.js
Ahora solo nos queda arreglar lo del useContext(), para esto utilizaremos un custom hook, específicamente crearemos ahora un hook reemplazando a TodoProvider por useTodos que será nuestro hook.
En este reemplazaremos el componente que estábamos retornando, por un objeto el cual tendrá todas las propiedades que necesitemos:
siguiendo la lógica de nuestra aplicación, este archivo lo tendremos que renombrar como useTodos, y enviarlo donde esta ubicado nuestro App.js porque como tal no es un componente.
Haremos lo mismo con el useLocalStorage porque tampoco es un componente.
En nuestro archivo App.js vamos a importar nuestro custom hook:
...import{ useTodos }from'./useTodos';...
Ahora si vamos a arreglar lo del useContext cambiandolo por nuestro custom hook:
Vamos a cambiar nuestro TodoForm para que ahora reciba las propiedades del useTodos.
/* Esto lo hacemos recibiendo a estos dos como valores de el
objeto que retorna useTodos */// De paso eliminamos el llamado a useContextfunctionTodoForm({ addTodo, setOpenModal }){...]
Ahora en nuestro App.js vamos a enviar nuestro addTodo.
functionApp(){const{... addTodo,}=useTodos();
Y vamos a enviar esta propiedad a nuestro Formulario en nuestro return.
Y listos 😎. Ya tenemos un código que es muchísimo más legible y menos complejo, aparte evitamos usar React.useContext() usando la composición de componentes.
Estuve dos horas buscando un error... eran los paréntesis de useTodos que olvide ponerlos... >__<
Me paso justamente los mismo! ha este punto ya me acostumbre a que me salgan errores y solo es cuestión de leer Track de errores jeje
Este curso me daba miedo el no entender, pero hasta ahora me está gustando mucho.
Pregunta ¿useLocalStorange y useTodos son hooks? Pues los he estado tratando como tal y los tengo en una carpeta de hooks, pero viendo esta clase, comencé a dudar que es hooks..!
Si, ambos son hooks. El profesor en una de las clases dijo que para el proyecto no habria problema en tener los hooks en la misma carpeta del component App ya que solamente se usaran desde ahi. Pero ya es gusto de cada desarrollador la organizacion de las carpetas y archivos
Yo personalmente tengo mi carpeta de "customHooks" y ahí los dejo, no los pongo en App. Me parece más arreglado así y no me vuelvo tan loco buscando después xd
Composición de componentes sin React Context
.
A un principio teníamos la aplicación dividida de en App y AppUI.
.
.
Pero nos damos cuenta que utilizar React Context es innecesario, debido a que solo estaríamos pasando información de App a AppUI. Por lo cual, decidimos eliminar el componente AppUI y mover su información al componente App.
.
.
Entre lo más destacable en el componente App se pasó la estructura de AppUI, debido a que ya no se utilizará React Context se va a sustituir a React.useContext(TodoContext) por el custom hook useTodos.
.
Además se eliminó el archivo AppUI.js y se renombró el provider TodoProvider por el custom hook useTodos con el nombre del archivo 'useTodos.js'. Finalmente useTodos.js y useLocalStorage.js se movieron dentro de la carpeta App modificando también todas las rutas de importaciones pertinentes.
.
.
Por lo que se elimina el uso de React Context pasando las propiedades pertinentes como parámetros, se modifica el componente App agregando dichas propiedades (en este caso solo faltaba agregar addTodo) a las que recibimos de useTodos y pasamos esa información al componente TodoForm desde el componente principal App.
.
.
Gracias a estos cambios logramos bajar la complejidad de la aplicación!.
WAO!!, casi un año con React y ni idea de esto. ¡Gracias platzi, gracias juan! ¡Aprendí un montón!
Pobre React Context. Destrozado en segundos.
Me he quedado sorprendido eh, esto es lo maximo.
Esto parece una buena opción pero siempre debemos analizar los tresholds en este caso perdimos estado global porque no es necesario en esta aplicación pero ganamos lógica reutilizable. Aunque, si no tenemos la jerarquía correctamente y creemos que podemos usar ese hook en componentes hijos estaríamos en un error porque se crea una nueva instancia.
No he entendido muy bien cuando usaríamos React Context y cuando usaríamos composición de componentes.
No representa si usamos el child el en header no se podría reutilizar el componente y mismo en todos los componentes con los que usamos child?
Utilizar React context no debería eximirse de hacer una buena composición de componentes, en muchos casos esto bastara para una correcta comunicación entre los mismos, pero en aplicaciones más grandes probablemente necesitarás implementar context cuando necesites compartir datos globales en la aplicación que son necesarios en varios componentes en diferentes niveles de la jerarquía.
mmm bueno en estos ejemplos esta claro, pero me nace una duda, voy a poner un ejemplo tengo la siguiente estructura de carpetas;
src
con esta base digamos lo siguiente, en app.js tengo un idUser que es el id del usuario que trabaja actualmente en el aplicativo. Tengo un UiFormSaveTask.js que es donde tengo como su nombre lo dice la vista del formulario y un useSaveTask.js que es donde tengo toda la lógica incluyendo las validaciones del formulario, los llamados al api y etc...
En app.js yo llamo <UiFormSaveTask/> como esta el ejemplo de la clase de hoy, aca es donde viene la pregunta: como puedo yo obtener ese idUser.js pero dentro de useSaveTask.js para cuando yo haga el post al api allí pueda enviar el id del usuario que registro esa tarea....
Espero ser claro con el ejemplo, quedo atento gracias
No se si entendí muy bien tu pregunta pero creo que una solución sería pasar como props el idUser a UiFormSaveTask presente en la composición y luego dentro de este pasar ese idUser como parámetro del CustomHook useSaveTask. Espero haberte ayudado.
WOW 🤯 Justamente estaba inconforme en el proyecto en el que me encuentro porque no me gustaba el tener varios contextos en mi App.js para manejar la información de unos ítems que se usan a través de algunas de las rutas/páginas de mi proyecto y la manera en que creas el custom hook para reemplazar el contexto me abrió la mente a muchas posibilidades!!!.
Entonces me surgen las dudas ¿Qué criterios tienes en cuenta a la hora de decidir entre hacer un custom hook y crear un contexto? ¿Tienes en cuenta el número de rutas que comparten información o es más acerca de los tataranietos que puedan necesitar dicha información?
:one: ¿Qué criterios tienes en cuenta a la hora de decidir entre hacer un custom hook y crear un contexto?
.
Con React Context podemos compartir un mismo estado entre varios componentes.
.
Con un Custom Hook podemos compartir una misma lógica para manejar el estado, pero cuando lo llamemos desde varios componentes no estaremos compartiendo el mismo estado, sino creando diferentes estados (que funcionan exactamente igual, pero al fin y al cabo son estados independientes).
...
:two: ¿Tienes en cuenta el número de rutas que comparten información o es más acerca de los tataranietos que puedan necesitar dicha información?
.
Yo creo que hay que tener en cuenta ambas.
.
Si usamos herramientas como React Router y necesitamos información compartida entre varias rutas, automáticamente voy a usar React Context.
.
Pero también voy a tener muy en cuenta la cantidad de componentes hacia abajo que haya en nuestra aplicación, incluso si viven dentro de una sola ruta.
Tengo el siguiente error
era porque el return estaba en () y no en {} en el useTodos.js
Creo que todos estamos igual, ahora entendemos más nuestra aplicación y podemos probar todo lo que queramos. Excelente clase!