Introducción
La forma en que fluye la información en React (desde un Componente Padre hacia un Componente Hijo) fuerza al desarrollador a ubicar el State en los Componentes superiores del Árbol de Componentes. Con aplicaciones chicas, en dónde no hay necesidad de que nuestro Árbol sea excesivamente grande, esto no suele ser un problema. Ahora bien, cuando las aplicaciones empiezan a crecer y el mismo valor de State debe estar presente en Componentes muy por debajo del Componente que lo contiene, es cuando nos enfrentamos con el problema del «prop drilling».
Llamamos «prop drilling» a la necesidad de hacer un «pasa mano» en el que algunos Componentes reciben una prop con el único objetivo de pasarla a uno de los Componentes que contiene. Esta práctica dificulta muchísimo mantener correctamente las distintas actualizaciones de State y, por tanto, complica la corrección de errores.
Otro problema que enfrentamos cuando trabajamos con React es la imposibilidad de comunicar dos Componentes que se encuentren al mismo nivel en el Árbol de Componentes (hermanos) sin involucrar a un Componente superior (padre) en el proceso.
Existen librerías externas, por ejemplo react-redux que se pueden agregar para dar solución a estos problemas. Context API es una solución nativa, es decir, tenemos acceso a ella simplemente por el hecho de estar trabajando con React.
Context API - Crear Contexto
En el post ReactJS: Higher Order Component Vs. Hooks Personalizados, hablamos de dos de los conceptos que se utilizan para crear un Contexto. La Composición y los HOC.
Un Contexto es un archivo que se divide en dos partes. Por un lado, la creación del espacio de almacenamiento y, por el otro, la creación del Provider.
El espacio de almacenamiento se genera con la función createContext(default). Esta función recibe un valor que se aplicará en caso de que no defina ningún Provider. El uso del valor por defecto no es obligatorio, pero es una buena práctica para evitar que se rompa la aplicación en caso de error con el Provider.
El Provider es un Componente que aplica Composición para permitir que sus children accedan a los valores almacenados en el espacio de memoria. El Provider se arma mediante la declaración de una función que tiene que retornar el Componente<Contexto.Provider>. Este Componente es posible gracias a la creación del espacio de almacenamiento que hicimos con createContext().
El Provider recibe la props value, en ella debemos poner todos los datos que necesitamos hacer accesibles a los children.
Dentro del Provider podremos utilizar los Hooks useState y useEffect de la misma forma que en cualquier Componente. Esto permite que un Provider manipule el Ciclo de Vida de los Componentes que acceden a sus valores. Si un valor del Provider cambia, todo Componente que acceda a ese valor es debidamente actualizado.
Una vez creados, debemos exportar el Provider y el Contexto. Por convención, usamos export para el Provider y export default para el Contexto.
Context API - Uso del Contexto
Una vez generados el Contexto y el Provider necesitamos asegurarnos que los Componentes deseados tengan acceso. Para ello debemos envolverlos en el Provider.
Hacer esto permite que cualquier Componente que se encuentre dentro del Provider sea capaz de utilizar el Hook useContext(Contexto) para acceder a los datos almacenados. useContext(Contexto) devuelve los datos que se encuentran dentro de la prop value del Componente Provider.
Redes