# 07 estado global simple `[@microapp/clock]` - A nivel de microapp, tendremos que: - Recibir el `globalStore` a traves de la interfaz de microapp. - Pasarselo a nuestro provider de estado común (`CommonStateProvider`) para que lo 'proxyfique'. - Lo primero que vamos a hacer simplemente por enfatizar aque ahora nuestro `CommonStateProvider` va a exponer un estado global, es cambiarle el nombre: ```text [VSCode RENAME] CommonStateProvider -> GlobalStateProvider CommonStateType -> GlobalStateType CommonStateDispatchType -> GlobalStateDispatchType CommonStateContext -> GlobalStateContext CommonStateDispatchContext -> GlobalStateDispatchContext useCommonState -> useGlobalState useCommonStateDispatch -> useGlobalStateDispatch [RENAME] common-state.context.tsx -> global-state.context.tsx ``` `[@microapp/clock] microapp.entrypoint.tsx` ```diff import "./microapp.styles"; import React from "react"; import ReactDOM from "react-dom"; import { History } from "history"; + import { RoutesProvider, GlobalStateProvider, GlobalStateType } from "./core"; import { MicroappRouter } from "./microapp.router"; /** * Microapp component */ const Microapp: React.FC<MicroappConfiguration> = ({ history, baseName, globalStore }) => ( <RoutesProvider baseName={baseName}> + <GlobalStateProvider globalStore={globalStore}> <MicroappRouter history={history} /> </GlobalStateProvider> </RoutesProvider> ); /** * Microapp public interface */ export interface MicroappConfiguration { history: History; baseName: string; + globalStore: GlobalStateType; } export type MicroappRenderFunction = (container: Element, config?: MicroappConfiguration) => void; export type MicroappUnmountFunction = (container: Element) => boolean; ... ``` `[@microapp/clock] microapp.d.ts` - Actualizo el ambient file de tipado: ```diff export interface MicroappConfiguration { history: History; baseName: string; + globalStore: object; } ``` `[@microapp/clock] standalone.entrypoint.tsx` - Actualizo también el standalone entrypoint con un `globalStore` mockeado: ```diff import "./standalone.styles"; import { MicroappInterface } from "./microapp.entrypoint"; import { createHashHistory } from "history"; MicroappInterface.render(document.getElementById("root"), { baseName: "", history: createHashHistory(), + globalStore: { timeZone: "Local" }, }); ``` `[@microapp/clock] core/global-state.context.tsx` - Y aqui es donde viene la parte más importante. Tenemos que hacer `mirroring` del `globalStore` en nuestro `GlobalStateProvider`. Es decir, tener una especie de proxy local, que expondremos a través del `value` del contexto, **con los valores del globalStore que me interesan y solo con ellos**, pero además, cada vez que hay un cambio en ese proxy sincronizo el `globalStore` y lo actualizo con dichos cambios. ```diff import React from "react"; export type TimeZone = "Local" | "Tokyo" | "New York"; export interface GlobalStateType { timeZone: TimeZone; } export type GlobalStateDispatchType = React.Dispatch<React.SetStateAction<GlobalStateType>>; // Context export const GlobalStateContext = React.createContext<GlobalStateType>(undefined); export const GlobalStateDispatchContext = React.createContext<GlobalStateDispatchType>(undefined); // Consumer export const useGlobalState = () => React.useContext(GlobalStateContext); export const useGlobalStateDispatch = () => React.useContext(GlobalStateDispatchContext); // Provider + export const GlobalStateProvider: React.FC<{ globalStore: GlobalStateType }> = ({ + globalStore, + children, + }) => { + const [globalState, setGlobalState] = React.useState<GlobalStateType>(globalStore); + // Función para MUTAR global store con lo que contenga global state. + // Esta solución no es elegante, y además es problemática ya que aquellos + // componentes que utilicen el estado global no se 'enterarán' de los cambios + // que provoca esa mutación. + React.useEffect(() => { + Object.assign(globalStore, globalState); + console.log("***", globalStore); + }, [globalState, globalStore]); return ( + <GlobalStateContext.Provider value={globalState}> + <GlobalStateDispatchContext.Provider value={setGlobalState}> {children} </GlobalStateDispatchContext.Provider> </GlobalStateContext.Provider> ); }; ``` `[@microapp/clock] components/settings.component.tsx` - Por último, simplemente por consistencia de nombres, cambiamos: ```diff export const Settings: React.FC = () => { const { timeZone } = useGlobalState(); + const setGlobalState = useGlobalStateDispatch(); const history = useHistory(); const routes = useRoutes(); const handleRadioClick = event => { event.persist(); + setGlobalState({ timeZone: event.target.value }); }; const handleClickSettings = () => history.push(routes.widget); ... } ``` `[@microapp/clock]` - Hacemos prueba rápida para ver que todo funciona y dejamos lista nuestra compilacion: ```text npm start npm run build:microapp:dev ``` ## Ejercicio Hacer lo mismo para el módulo `@microapp/quote`, seguir los mismo pasos. ### Solución Seguir los mismos pasos que para `@microapp/clock`, es idéntico. La única diferencia ahora es que le daremos como valores por defecto a nuestro estado en standalone.entrypoint los siguientes: `[@microapp/clock] standalone.entrypoint.tsx` ```diff import "./standalone.styles"; import { MicroappInterface } from "./microapp.entrypoint"; import { createHashHistory } from "history"; MicroappInterface.render(document.getElementById("root"), { baseName: "", history: createHashHistory(), + globalStore: { grayscale: true, blurLevel: 5 }, }); ```