Skip to content

Instantly share code, notes, and snippets.

@jvanbruegge
Created April 4, 2019 13:15
Show Gist options
  • Save jvanbruegge/9af17f4f5fca8bb3e6198ebe65afac55 to your computer and use it in GitHub Desktop.
Save jvanbruegge/9af17f4f5fca8bb3e6198ebe65afac55 to your computer and use it in GitHub Desktop.
My withLocalState combinator, soon to be published seperately
type SimpleMerge<Global, Local> = { global: Global, local: Local };
interface Merger<Global, Local, T> {
merge(g: Global, l: Local): T;
extract(t: T): SimpleMerge<Partial<Global>, Partial<Local>>;
}
function withLocalState<Global, Local, T = SimpleMerge<Global, Local>>(component: Component<T>, merger?: Merger<Global, Local, T>, stateChannel = 'state', localChannel = '_localState'): Component<Global> {
const defaultMerger: Merger<Global, Local, SimpleMerge<Global, Local>> = {
merge: (global, local) => ({ global, local }),
extract: identity
};
const wrapper = function WithLocalState(sources: any) {
const m = merger ? merger : defaultMerger;
const state$ = xs.combine<Global, Local>(sources[stateChannel].stream, sources[localChannel].stream.startWith(undefined))
.map(([g, l]) => m.merge(g, l))
.remember();
const sourcesCopy = { ...sources };
delete sourcesCopy[localChannel];
const sinks: any = component({ ...sourcesCopy, [stateChannel]: new StateSource<T>(state$, 'withLocalState') });
const updated$ = !sinks[stateChannel] ? xs.never() :
sinks[stateChannel]
.compose(sampleCombine<any>(state$))
.map(([fn, x]: any) => m.extract(fn(x)));
const global$ = updated$.map((s: any) => (state: Global) => ({ ...state, ...s.global }));
const local$ = updated$.map((s: any) => (state: Local) => ({ ...state, ...s.local }));
return {
...sinks,
[stateChannel]: global$,
[localChannel]: local$
};
};
return withState(wrapper as any, localChannel) as any;
}
const customMerger: Merger<MainState, LocalState, State> = {
merge: (g, l) => ({ ...l, authToken: g.authToken }),
extract: t => ({ global: { authToken: t.authToken }, local: omit(['authToken'], t) })
};
export const Login = withLocalState<MainState, LocalState, State>(LoginComponent, customMerger);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment