# 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 },
});
```