Skip to content

Instantly share code, notes, and snippets.

@typoerr
Created July 22, 2017 13:46
Show Gist options
  • Select an option

  • Save typoerr/28d1ae8e734f931f0793174dfa0092ee to your computer and use it in GitHub Desktop.

Select an option

Save typoerr/28d1ae8e734f931f0793174dfa0092ee to your computer and use it in GitHub Desktop.
propsをstreamで受け取れるようにするpreact hoc

propsをstreamで受け取れるようにするpreact hoc

initial propsを受け取りに難がある。完成度が低い。

import { h, Component, ComponentConstructor, FunctionalComponent } from 'preact';
import { Stream, Subscription, mergeArray } from 'most';
import { noop, hasOwn } from '@utils';
export type AnyComponent<P> = ComponentConstructor<P, any> | FunctionalComponent<P>;
export type StreamableProps<P> = {
[K in keyof P]: Stream<P[K]> | P[K]
};
export function isStream(x: any) {
return x instanceof Stream;
}
export default function observer<P>(component: AnyComponent<P>, initProps?: Partial<P>) {
return class ObserverComponent extends Component<StreamableProps<P>, {}> {
static displayName = `Observer(${component.name})`;
subscriptions: Subscription<any>[] = [];
currentProps: any = initProps || {};
constructor(props: StreamableProps<P>, context: any) {
super(props, context);
}
componentWillMount() {
const p: any = this.props;
const streams: Stream<any>[] = [];
for (const k in p) {
if (!hasOwn(p, k)) continue;
if (!isStream(p[k])) {
this.currentProps[k] = p[k];
continue;
}
const v = (p[k] as Stream<any>);
const s$ = v.tap(x => this.currentProps[k] = x);
streams.push(s$);
}
// reduce synchronous streams by debounce
const sub = mergeArray(streams).debounce(0).subscribe({
next: () => this.forceUpdate(),
error: (e: Error) => { throw e; },
complete: noop
});
this.subscriptions.push(sub);
}
componentWillUnMount() {
this.subscriptions.forEach(x => x.unsubscribe());
}
componentWillReceiveProps(p: any) {
for (const k in p) {
if (!hasOwn(p, k) || isStream(p[k])) continue;
this.currentProps[k] = p[k];
}
}
render() {
return h(component, this.currentProps, this.props.children!);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment