Usar Context en React

Usar Context en React

Cuando hablamos de una aplicación común de React, los datos generalmente se pasan por jerarquía (de un componente "padre" a "hijo" a través de estados, o de un componente "hijo" a "padre" mediante funciones). Sin embargo, esta forma de compartir información se vuelve muy complicada y extensa cuando hay muchos componentes involucrados o muchos niveles de jerarquía.

Es para resolver este problema que traemos en este artículo una forma de compartir datos globales sin ninguna complejidad en el código utilizado, a través de una característica de React llamada Context. ¿Me acompañas a conocerla?


¿Por qué utilizar Context?


Antes de explicar cómo usar Context, es necesario resaltar su importancia y cuánto nos puede ayudar. Para ello, abordemos el ejemplo de una aplicación en la que tiene sentido su uso: imagina la siguiente jerarquía dentro de un proyecto:

Figura 1: Esquema de proyecto Context-Project.

En la aplicación Context-Project tenemos un componente App que tiene otros dos que llamamos Form y Presentation. Form es el encargado de recolectar los datos del usuario, mientras que Presentation muestra estos datos a través del componente Data implementado en el mismo.

Si tuviéramos que usar estados y props para pasar los datos completados en Form y presentarlos en Data, sería necesario crear estados en App que se pasarían a través de props a Presentation. Esto, a su vez, también pasaría los datos al componente Data a través de props (está empezando a volverse repetitivo, ¿no?).

Además, dado que Form es responsable de recopilar los datos, los estados de la aplicación deben actualizarse por ella, lo que genera la necesidad de pasar a Form vía props funciones que modifican estos estados. Muy extenso, ¿no crees? ¿Qué pasaría si dijéramos que es posible enviar estos datos a un lugar determinado a través del componente Form para que los Datos puedan acceder a ellos directamente? Así es, estamos hablando de Context.

Con Context es posible crear un archivo que almacenará todos los datos y métodos para cambiarlos, de modo que cualquier componente previamente permitido pueda acceder y utilizar la información guardada.

Primeros pasos

Usaremos el esquema de la Figura 1 para crear un proyecto que use Context. Entonces, comencemos creando el proyecto a través de nuestra terminal con los siguientes comandos a continuación (si todo va bien, se cargará una página en tu navegador con el logotipo de React):

npx create-react-app context-project

cd context-project

npm install

npm start

💡
Nota: Se utilizó npm como herramienta de manejo de paquetes, pero siéntete en libertad de emplear otra opción.


Ahora es el momento de crear el componente Form que enviará los datos a Presentation y Data. Tendrá algunas entradas de texto, fecha y número, donde se puede completar el nombre de un proyecto, la fecha de finalización, la cantidad de personas involucradas y un enlace de imagen. Toda esta información rellenada se guardará en los estados locales pertenecientes al Form:

Figura 2: Componente Form.

Es posible ver que los valores guardados en los estados aún no se han utilizado para nada, pero esto lo resolveremos en los próximos pasos con la creación de Context.

Estructurar Context

La primera acción es crear el archivo donde almacenaremos la información relativa a las variables globales a las que tendrán acceso todos los componentes. Esta acción la realiza la función createContext, que importaremos desde la biblioteca react. CreateContext se almacenará en una constante y se exportará para que podamos usarlo en el resto de la aplicación:

Figura 3: Creación de context.

Una vez realizada la ubicación de almacenamiento de nuestras variables globales, ahora necesitamos crear una función que se encargará de manipular la información guardada en Context y proporcionarla al resto del código. Para ello, llevaremos a cabo cinco pasos:

  • Importar el archivo context que acabamos de crear (el nombre context será sustituido por el que des al archivo context donde se encuentra la función createContext);
  • Insertar la propiedad children en la función, que brinda acesso a todos los “hijos” de un determinado componente;
  • Crear un componente context.Provider, responsable de proveer los datos de context para el resto de la aplicación;
  • Añadir una propiedad a este componente context.Provider llamada value, que recibirá como valor los datos disponibles para el proyecto (la propiedad value es obligatoria y, sin ella, no funcionará nuestra implementación;
  • Insertar dentro del componente context.Provider el elemento children que nós trajimos vía props.
Figura 4: Creación de la función que manipulará context para el proyecto.

Hecho esto, creamos la estructura básica de nuestro context. Todavía no tiene información para compartir (de ahí las comillas como el valor de valor), pero está listo para hacerlo. Esto es lo que haremos ahora.

Manipular el Context


Como ya se mencionó, la función ProjProvider es responsable de crear, manipular y proporcionar datos al context. Ampliemos estos tres conceptos en detalle para que nada se pase por alto y domines por completo esta funcionalidad.

En el proyecto que usamos como ejemplo, hay cuatro datos importantes: el nombre del proyecto, la fecha de finalización, el número de participantes y el enlace de la imagen. Esta información ya está guardada en el Form, pero solo él tiene acceso a ellos. Para que todos los componentes puedan obtener estos datos a través del context, también debemos crearlos en ProjProvider.

Quizás te preguntes por qué existen estos estados en el componente Form si también se crearán en el ProjProvider, pero aquí hay una sugerencia importante: para este caso y similares, es mucho más rentable enviar toda la información al context (a través de onClick ) que cada cambio dentro de una de las entradas (a través de onChange). Esta última manera generaría una serie de renders innecesarios para la aplicación.

Figura 5: Creación de los estados globales de context.

Una vez que creados los estados que almacenan la información, ahora necesitamos manipularlos. Cualquier función que sirva para este propósito también debe crearse en ProjProvider.

Queremos que, al hacer clic en el botón Add existente en Form, todos los valores de los estados locales de este componente sean enviados al estado global ubicado en ProjProvider. Para ello, crearemos una función de actualización que recibirá como parámetro los cuatro estados locales del Form y los almacenará en los estados globales.

Figura 6: Creación de la función de manipulación de los estados globales.

También necesitamos otorgar a los otros componentes la posibilidad de acceder tanto a la función que creamos como a los estados globales, según cada necesidad de implementación. Para este propósito, podemos crear una constante que almacene todo lo que se debe compartir y pasar esta constante como el valor de la propiedad de valor de context.Provider, como se muestra en la siguiente figura:

Figura 7: Hacer accesibles los dados de context para los demás componentes.

El siguiente paso es encapsular cada parte de nuestra aplicación que pueda acceder a lo que crea, manipula y otorga el componente ProjProvider (esto es para lo que estamos usando niños, para que todo dentro del componente tenga acceso al contexto). Haremos esto en el componente principal de la aplicación.

Figura 8: Encapsulando el código con el componente ProjProvider.

Una vez que creados los estados necesarios y construidos los métodos para manejarlos y otorgarlos, necesitamos acceder a estas funciones con los componentes Form y Data. Aquí es donde entra en juego el hook useContext.

UseContext


En el componente Form, realizaremos dos nuevas importaciones: el hook useContext de la biblioteca react y el archivo context desde donde lo creamos.

Luego, generaremos una constante que recibirá la llamada de este hook, donde el contexto se pasará como su parámetro. Finalmente, extraemos de esta constante creada lo que está en el context que es necesario para la implementación (en este caso, solo la función update).

La función de actualización se utilizará en el evento de clic del botón, donde pasaremos los cuatro estados locales como parámetro.

Figura 9: Método de acesso a la función update por medio del componente Form.

¡Todo bien! Ahora ya actualizamos el context a través de las entradas creadas en el componente Form. Sigue ahora acceder a los estados globales para mostrar esta información a través del componente Data. La forma en que lo hacemos no es muy diferente a lo visto hasta ahora: necesitaremos realizar las mismas importaciones, con la diferencia de que lo que traerás del context no será la función de actualización, sino los cuatro estados globales, creadas en ProjProvider:

Figura 10: Componente Presentation.
Figura 11: Componente Data.
Figura 12: Código en ejecución.

Sencillo, ¿verdad? Después de estos pasos, ¡nuestro proyecto funciona de la manera que lo planeamos!


Consideraciones finales

Context es una herramienta increíblemente simple de usar cuando se trata de la gestión de datos. Sin embargo, se deben tomar algunas precauciones. Notarás que, cuanto más grande sea tu aplicación, más y más estados y funciones se crean en el Proveedor (ProjProvider), lo que hace que el componente sea largo e incluso complicado para hacer referencia o encontrar algo.

De esta forma, si el proyecto que vas a crear es robusto o empieza a serlo, es interesante y recomendable usar más de un context (no cambia mucho y solo necesitas repetir el mismo proceso se muestra en las figuras 3, 7 y 8), por lo que cada archivo se encarga de un área determinada de la implementación.

¡Buena implementación! ¡Éxito!

💡
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Listopro.

Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.