DEV Community

Cover image for Provider en React con JavaScript
Sazardev
Sazardev

Posted on

Provider en React con JavaScript

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") || "",
};
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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" });
Enter fullscreen mode Exit fullscreen mode

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;
  }
};
Enter fullscreen mode Exit fullscreen mode

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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: () => {},
});
Enter fullscreen mode Exit fullscreen mode

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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)