You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

48 lines
1.4 KiB

import * as React from "react";
import { AppState } from "@client/state";
const StateContext = React.createContext<AppState | null>(null);
export interface ProvideStateProps {
state: AppState;
children: React.ReactNode;
}
export function ProvideState({ state, children }: ProvideStateProps) {
return (
<StateContext.Provider value={state}>{children}</StateContext.Provider>
);
}
export interface ConsumeStateProps {
children: (state: AppState) => React.ReactNode;
}
export function ConsumeState({ children }: ConsumeStateProps) {
const consumeState = (state: AppState | null) => {
if (state == null) {
throw new Error(
"Component with ConsumeState must be mounted inside ProvideState"
);
}
return children(state);
};
return <StateContext.Consumer>{consumeState}</StateContext.Consumer>;
}
export function injectState<P extends { appState: AppState }>(
Component: React.ComponentType<P>
): React.FunctionComponent<Omit<P, "appState">> {
return function InjectState(props) {
const state = React.useContext(StateContext);
if (state == null) {
throw new Error(
"Component with injectState must be mounted inside ProvideState"
);
}
// tslint:disable-next-line: no-object-literal-type-assertion
const allProps: Readonly<P> = {...props, appState: state} as Readonly<P>;
return <Component {...allProps} />;
}
}