El patrón de comportamiento Provider es un patrón de diseño que se utiliza para proporcionar datos a otros componentes. Donde la idea principal es que un componente padre proporcione datos a sus componentes hijos a traves de un arbol de componentes e inyectar dependencias a los componentes hijos de otros Providers.
Provider es además aquel encargado de crear, almacenar y proporcionar los datos a los componentes hijos, donde la procedencia de esta información puede ser de una API, un archivo JSON, una base de datos, etc. Para un Provider le es indistinto la procedencia de la información, y es algo que no debe importarle, solo debe manejarla y asegurarse de que la información recibida sea la solicitada.
Componentes iniciales
Para la creación de un Provider se requiere plantear su estructura antes de utilizarlo, donde se necesita definir, a que modulo pertenece, con qué información se va a trabajar, y que funciones se van a utilizar para manipular la información. Por ende, necesitamos previamente un servicio que contenga comunicacion con la información, y un modelo que nos permita manipular la información.
Crear un Provider en React con JavaScript
Para crear un Provider escalable, mantenible y reutilizable, se debe seguir una estructura que permita la manipulación de la información de manera eficiente. Para React con JavaScript, es necesario crear alrededor de cinco archivos, donde estos comprenden: Contexto Global, Acciones, Reducer, Provider y Estado Inicial.
Estado Inicial
El Estado Inicial es el encargado de almacenar la información que se va a utilizar en los componentes hijos, y se encarga de proporcionar la información a los componentes hijos. Para crear un Estado Inicial se debe utilizar la siguiente estructura:
GlobalState.js
export const GlobalState = {
// Informacion inicial
// Aqui se extrae tambien la informacion local
usuario: localStorage.getItem("usuario") || "",
};
Contexto Global
El Contexto Global es el encargado de almacenar la información que se va a utilizar en los componentes hijos, y se encarga de proporcionar la información a los componentes hijos. Para crear un Contexto Global se debe utilizar la siguiente estructura:
GlobalContext.js
import React, { createContext, useReducer } from "react";
const GlobalContext = createContext({
state: GlobalState,
dispatch: () => {},
// Funciones extras
});
Acciones
Las Acciones son las funciones que se encargan de manipular la información del Estado Inicial, donde estas funciones se encargan de modificar la información del Estado Inicial. Para crear Acciones se debe utilizar la siguiente estructura:
GlobalActions.js
export const setUsuario = (dispatch, usuario) =>
dispatch({ type: "SET_USUARIO", payload: usuario });
export const clearUsuario = (dispatch) => dispatch({ type: "CLEAR_USUARIO" });
Reducer
El Reducer es el encargado de modificar la información del Estado Inicial, donde este se encarga de recibir las Acciones y modificar la información del Estado Inicial. Para crear un Reducer se debe utilizar la siguiente estructura:
GlobalReducer.js
export const GlobalReducer = (state, action) => {
switch (action.type) {
case "SET_USUARIO":
return { ...state, usuario: action.payload };
case "CLEAR_USUARIO":
return { ...state, usuario: "" };
default:
return state;
}
};
Provider
El Provider es el encargado de proporcionar la información a los componentes hijos, donde este se encarga de almacenar la información del Estado Inicial y proporcionarla a los componentes hijos. Para crear un Provider se debe utilizar la siguiente estructura:
GlobalProvider.jsx
export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(GlobalReducer, GlobalState);
return (
<GlobalContext.Provider value={{ state, dispatch }}>
{children}
</GlobalContext.Provider>
);
};
Colocación del Provider
Para que el Provider pueda ser utilizado en los componentes hijos, se debe colocar en donde es requerido, aunque sea tentador colocarlo en el componente raíz, no es recomendable, ya que puede causar problemas de rendimiento. Para colocar el Provider se debe plantear correctamente el alcance que deseas que tenga este Provider, así que antes de colocarlo, plantea si es necesario que TODOS los componentes van a requerir accesar a la información del Provider o solamente es un módulo aislado que solo requiere lo necesario para sí mismo.
App.js
import { GlobalProvider } from "./GlobalProvider";
function App() {
return (
<GlobalProvider>
<Componente />
</GlobalProvider>
);
}
Consumir el Provider
Para consumir el Provider en los componentes hijos, se debe utilizar el Hook useContext
que proporciona React. Para consumir el Provider se debe utilizar la siguiente estructura:
Componente.jsx
import { useContext } from "react";
import { GlobalContext } from "./GlobalContext";
const Componente = () => {
const { state, dispatch } = useContext(GlobalContext);
return (
<div>
<h1>{state.usuario}</h1>
</div>
);
};
Funciones personalizadas
A veces es necesario crear funciones personalizadas que no estén relacionadas con el Estado Inicial, para esto se puede agregar funciones extras al Contexto Global. Para agregar funciones extras al Contexto Global se debe utilizar la siguiente estructura:
GlobalContext.js
import React, { createContext, useReducer } from "react";
const GlobalContext = createContext({
state: GlobalState,
dispatch: () => {},
// Funciones extras
logoutAndRedirect: () => {},
});
GlobalProvider.jsx
export const GlobalProvider = ({ children }) => {
const navigate = useNavigate();
const [state, dispatch] = useReducer(GlobalReducer, GlobalState);
const logoutAndRedirect = () => {
dispatch({ type: "CLEAR_USUARIO" });
navigate("/");
};
return (
<GlobalContext.Provider value={{ state, dispatch, logoutAndRedirect }}>
{children}
</GlobalContext.Provider>
);
};
Recomiendo altamente utilizar las funciones personalizadas cuando se requiere trabajar con el estado del Provider e involucra otros procesos o gestionamiento de muchos cambios en el estado. Esto con el fin de reducir la cantidad de codigo que puede llegar a involucrarse en el lado de la Vista, y mantener un orden en la estructura del Provider, promoviendo asi la reutilizacion de codigo y la escalabilidad del mismo.
Top comments (0)