Jonathan Guidi
Randy Ochoa
Christian Ramirez
El manejo eficiente de los datos y el estado dentro de las aplicaciones React es una pieza fundamental para garantizar un desarrollo escalable y un rendimiento óptimo. Recientemente hemos avanzado al aprender sobre React Context, una herramienta diseñada para evitar el tedioso "prop drilling" o la necesidad de pasar props a través de varios niveles de componentes que no las utilizan directamente. Pero hoy, avanzaremos un paso más allá explorando el uso del hook useContext, que puede simplificar aún más la forma en que accedemos a nuestro contexto en componentes React, haciendo nuestra vida como desarrolladores mucho más cómoda y, por qué no, también más estética.
¿Qué es el prop drilling y cómo puede ayudarnos React Context?
Para comprender cómo useContext mejora nuestro flujo de trabajo, es esencial entender primero el problema que aborda. El "prop drilling" se refiere a la práctica de pasar datos a través de una jerarquía de componentes en React, incluso a aquellos que no necesitan esos datos para su funcionamiento. Esto puede complicar el mantenimiento del código y dificultar el seguimiento del flujo de datos.
¿Cómo funciona useContext para acceder al contexto global?
El hook useContext nos permite suscribirnos a un contexto React dentro de un componente funcional. Basta con proporcionarle al hook el contexto deseado para que useContext haga "la magia" de compartir los datos necesarios directamente con el componente que los requiere.
useContext desde React.useContext y le pasamos el contexto que queremos consumir.¿Cómo simplifica useContext nuestro código?
En lugar de envolver nuestros componentes con un componente Consumer y usar una función render para acceder al contexto, useContext nos permite hacerlo en una sola línea de código. Esto resulta en un código más limpio y legible.
Consumer.¿Puede useContext reemplazar completamente al Consumer?
Si bien useContext simplifica y mejora la legibilidad del código, hay situaciones en las cuales las render functions y el componente Consumer pueden ser más adecuados. Por ejemplo, algunas complejidades de implementación o detalles específicos de rendimiento a veces hacen que estas técnicas sean preferibles.
useContext y Consumer depende del caso de uso particular y las preferencias del desarrollador.Próximos pasos en tu aprendizaje de React
Una vez que te sientas cómodo utilizando useContext para acceder y manejar el contexto global de tu aplicación React, el siguiente paso en tu viaje de aprendizaje es explorar otras potentes herramientas dentro del ecosistema React, como los React Portals.
useContext y render functions.En resumen, useContext es una herramienta que todo desarrollador React debería tener en su conjunto de herramientas para escribir un código más limpio, modular y fácil de mantener. Al mismo tiempo, recuerda que el conocimiento de diferentes métodos para manejar el contexto es invaluable en situaciones donde la complejidad del proyecto lo requiera. ¡Continúa explorando, aprendiendo y mejorando tu código con cada nuevo proyecto!
Jonathan Guidi
Randy Ochoa
Christian Ramirez
Brayan omar cabrera diez
SANTIAGO CANO GONZALEZ
Thomas Ferreyra
Angel David Velasco Bonifaz
Erick Marty Terrazas Zeballos
Jose Ever Muñoz Muñoz
Marcelo Vinicio Chavarría Ugalde
Zahir La Rosa
Sebastian Joven
Zahir La Rosa
Andrés Julian Caro Restrepo
Jeefry Polo Ospina
Edgardo Luis Jimenez Nuñez
Jinny jose Cardenas labrador
Ariel Ezequiel Biazzo Genua
Irving Juárez
Haikel Mustafá
Max Andy Diaz Neyra
Carlos Esteban León Pinilla
Aris Manuel Cahuana
Josué Rubén Robles Gonzalez
Josué Rubén Robles Gonzalez
Moises Hernandez
Christopher Andrés Guano Valencia
Tomas Cejas
Tomas Cejas
Fernando Francisco López Mauro
Federico Arias
Ismael Cruz Procel
Gerson Pineda
Juan Castro
ProfesorGerson Pineda
Yeferson Lasso España
Al principio me pareció un poco confuso usar TodoContext.Provider, con useContext() es muchisimo más sencillo y legible!
La verdad si, mucho mejor useContenxt
Jonathan, solo por aclarar, siempre usas TodoContext.Provider, tan solo cambias el uso del TodoContext.Consumer por el useContext, pero tienes toda la razón es muchísimo más sencillo.
Pero en la vida profesional si aparecen muchos Context.Consumer
Según la documentación nueva oficial de React, manifiestan que no es recomendado usar Consumer y que poco a poco empezara a entrar en desuso, Entonces viva, useContext.
Direferncias al usar Context.Consumer con useContext.
Cuando necesitamos pasar los datos establecidos en el Context:
function TodoProvider({children}){ // Funcionalidades del provider return ( <TodoContext.Provider> {children} </TodoContext.Provider> ) }
La principal diferencia es el uso de TodoContext.Consumer dentro del componente que queramos comunicar con las props. Y el metodo por useContext que no implica pasar como si fuera un componente la sintaxis del Consumer.
<TodoContext.Consumer> { ({ props necesarias }) => { // Todos los componentes para pasar las props } } </TodoContext.Consumer>
const { props necesarias } = useContext(TodoContext)
Gracias a esa explicacion de la clase Que es React Context, ahora tiene sentido como se trae el contexto con el hook useContext.
Bueno pues en el momento de las clases anteriores donde el profe creo el componente AppUI , pues yo preferi no hacerlo y segui con el app normal metiendo todo ahi.
Esto me llevo a un pequeño problema al querer recrear lo que el profesor hizo en el video.
No podemos usar el
provideren el mismo lugar donde vamos a usar eluseContext. Me toco ponerlo en elindex.jspara que luego en el componenteAppme permitiera usar el use context.
Si le dejaba el provider ahi, pues se rompia todo
<>...</> y ya.
Por si a alguien mas le pasa, pues nada ese es el motivo que no funcione bien
excelente aporte, esto soluciona los errores
Yes that`s my case dude, thankS!
¿En que momento es más recomendable usar el contexto de la forma de la clase anterior? Se me mucho más sencillo y legible esta manera
Creo que queda a criterio del proyecto en cuestión o del programador como tal.
Es altamente recomendable utilizar el hook useContext() al comenzar un proyecto desde cero. Sin embargo, en el ámbito laboral, es posible que te encuentres con empresas que han adoptado la práctica de usar <TodoContext.Consumer>. En tales casos, podrías necesitar emplearlo. Esto se debe a que esta es la forma más antigua de trabajar con contextos en versiones anteriores de React.
Recuerda que, aunque useContext() es preferible, siempre es importante adaptarse al ambiente laboral específico y las prácticas existentes en el entorno de desarrollo.
Así solucioné el problema al usar el buscador
{((!loading && totalToDos == 0)) && <p>Crea tu primer Todo</p>} {((!loading && searchTodos == 0 && totalToDos > 0)) && <p>No hay coincidencias</p>}
Gracias. Yo hice básicamente lo mismo.
{(!loading && todosTotal == 0) && <EmptyTodos />} {(!loading && todosTotal > 0 && searchedTodos.length == 0) && <EmptySearchTodos />}
Tuve que traer todosTotal desde el contexto.
const { loading, error, searchedTodos, completarTodo, eliminarTodo, openModal, todosTotal // <- Este no estaba en el video } = useContext(TodoContext)
Les comparto una forma en la que me parece interesante exportar nuestros contexts. Esto sería creando nuestro propio hook para dicho context así:
// useStateContext.js import React, { createContext, useContext } from "react"; const Context = createContext(); export const StateContext = ({ children }) => { // ... Toda nuestra lógica return ( <Context.Provider value={{ // ... Nuestros valores a exportar }}> {children} </Context.Provider> ); } export const useStateContext = () => useContext(Context);
Como puedes ver, así exportaríamos nuestro StateContext y nuestro useStateContext, el cual ya utiliza el useContext; de esta forma, en los componentes podremos importarlos así:
// TuComponente.js import { useStateContext } from '../Context/useStateContext'; function TuComponente() { const {...tus valores a importar} = useStateContext(); return( <></> ); }
Así ya no tendremos que estarle indicando qué contexto queremos usar. Y en caso de tener varios contextos como nos enseña Juan, por ejemplo tener uno para los usuarios, otro para validaciones, ordenes... sería tan sencillo como importar dicho contexto y llamarlos como useUserContext(), useValidationContext(), useOrderContext()... según corresponda. 😀
Desde la clase anterior cuando implementamos Context mi app se murió :(
Nos podrias pasar tu repositorio para ver cual puede ser el problema.
Para ayudarme de vez en cuando uso comparar código (https://charactercalculator.com/es/text-compare/) o chat GPT.... y de ahí es mas fácil ver el error... e imagino que debe ser una práctica común en los programadores de los diferentes lenguajes.
All what I hear is: 1. Destructuring en todos lados.
Muy limpia la sintaxis del contexto, pero la logica del fetch handling sigue siendo muy compleja y dificil de leer. Yo creo que haciendo un state machine lo haria mucho más legible
En caso de que no queramos cambiar los nombres de las propiedades, podemos redefinirlos en el objeto. Algo útil si tenemos que cambiar muchas propiedades en muchos sitios
const { completedTodos: completed, totalTodos: total, } = React.useContext(TodoContext)
import { Contexto } from './direccionContexto/'
const { value } = React.useContext(Contexto)
useContext acepta un objeto de contexto (el valor devuelto de React.createContext) y devuelve el valor de contexto actual. El valor actual del contexto es determinado por la propiedad value del <MyContext.Provider> ascendentemente más cercano en el árbol al componente que hace la llamada.
Super cool, no conocía esto. Antes usaba solo Redux
¿Por qué es mejor usar useContext?
El hook useContext transforma por completo la legibilidad de tu código. En lugar de anidar tu interfaz dentro de un componente <Consumer> que utiliza una render function (una función que devuelve JSX), puedes simplemente declarar una variable al inicio de tu componente.
Al hacer esto, separas la lógica de extracción de datos de la estructura visual. Tu componente queda mucho más limpio, ya que solo invoca const datos = useContext(MiContexto) y luego se dedica exclusivamente a renderizar etiquetas HTML o componentes de React. Esto elimina la anidación profunda (conocida como callback hell en las interfaces) y hace que el mantenimiento del código sea mucho más rápido y menos propenso a errores visuales.
Sí, si llamas dos veces al mismo provider como en tu ejemplo, se crearán dos instancias distintas del proveedor. Cada instancia tendrá su propio estado y cambios en un provider no se reflejarán en el otro. Esto puede ser útil si necesitas contextos separados, pero si deseas compartir un mismo estado global, deberías utilizar solo una instancia del provider en la jerarquía de tu componente.
<App> <A1> <A2> <MyContext.Provider> <Consumer1/> </MyContext.Provider> </A2> </A1> <B1> <B2> <MyContext.Provider> <Consumer2/> </MyContext.Provider> </B2> </B1> </App>
Se podría decir que es mejor usar mas contextos para separar las responsabilidades de nuestra app. Un solo contexto cuando es algo simple y Redux cuando tenemos una app de gran escala?
Sí, aunque también depende de la empresa o de la solución que quieras realizar. También existe Zustand, que es más simple que Redux. Te comparto unas diferencias de un ingeniero de software:
Fuente: ¡No necesitas Redux en React! Aprende a usar Zustand, alternativa sencilla - Midudev
¡Nunca pares de aprender! 🚀🚀
Alguna ayuda con esto?
import React from 'react'; import { TodoCount } from './TodoPropiedades/TodoCount'; import { TodoList } from './TodoPropiedades/TodoList'; import { TodoSearch } from './TodoPropiedades/TodoSearch'; import { TodoItem } from './TodoPropiedades/TodoItem'; import { CreateTodoButton } from './TodoPropiedades/CreateTodoButton'; import { TodosLoading } from './TodoPropiedades/TodosLoading' import { TodosError } from './TodoPropiedades/TodosError/' import { TodoContext } from './TodoPropiedades/TodoContext'; import './App.css'; function App() { const {loading,error,filterTodos,completeTodo,deleteTodo} = React.useContext(TodoContext); return ( <React.Fragment> <main> <h1 className='title'>Todo-List</h2> <TodoCount/> <div className='search-div'> <TodoSearch/> </div> <div className='list-div'> <TodoList> {loading && <TodosLoading />} {error && <TodosError />} {filterTodos.map(todo => (<TodoItem key={todo.text} text={todo.text} completed={todo.completed} onComplete={()=>completeTodo(todo.text)} //Se encapsula la funcion dentro de otra para que se ejecute solo si es llamada onDelete={()=>deleteTodo(todo.text)} />))} </TodoList> </div> <CreateTodoButton/> </main> </React.Fragment> ); } export default App;
Hola! Tenia el mismo error, debes de poner tu TodoCounter dentro del Provider, si esta fuera del provider no se puede :)
Vengo siguiendo la clase como puedo, cambie cosas del codigo para darle mi impronta y llegue hasta aca y estoy 3 horas intentando hacer funcionar el useContext, no pude, tiro la toalla. Me parece muy confuso la manera en la que se aborda la clase, se mezcla el context provider de la anterior clase con esta, busque el curso de Custom Hooks para profundizar y no esta disponible, ojala lo esten mejorando. Voy a estar atento cuando salga. Lo bueno es que mi proyecto corre sin el useContext, a lo mejor tenga que implementarlo para agregar el boton, asi aprendo como usarlo en un componente. Como critica constructiva, seria bueno que veamos como usar el contexto con un solo componente, ya que al usar customhooks (localstorage) y otros estados dentro del contexto, se hace un poco dificil de comprender quien le esta pasando que a cada archivo,
Compartenos tu codigo para ver si podemos ayudar, en lo personal, también me parecen muchos conceptos en la misma clase.
Se pueden anidar providers?
Yep! Se termina viendo parecido a los callback hells :sweat_smile: pero ya ahí depende de ti y tu equipo si eso les gusta o no :D
Si, sería cuestión de definir bien el alcance de los Providers, gracias Juan
con tantas props al inicio, pense que eso era lo mas complicado de react y me estaba pareciendo un framework muy complicado, con el context ya todo tiene sentido jajaja