Skip to content

Instantly share code, notes, and snippets.

@pinyin
Created December 6, 2016 05:28
Show Gist options
  • Save pinyin/b3c671a9969f0c92cc0b6fbec862246c to your computer and use it in GitHub Desktop.
Save pinyin/b3c671a9969f0c92cc0b6fbec862246c to your computer and use it in GitHub Desktop.
Reactive React component with TypeScript
import * as React from 'react'
import {Subject, Observable, Scheduler} from 'rxjs'
import {ISubscription} from 'rxjs/Subscription'
import {createSubjects} from '../../../lib/rxjs-helpers/createSubjects'
import {Subjects} from '../../../lib/rxjs-helpers/Subjects'
import {Mapper} from "../../../lib/mapobject";
export abstract class AbstractComponent<Props, State, Interactions> extends React.Component<Props, State> implements React.ComponentLifecycle<Props, State> {
protected abstract readonly interactionFilters: InteractionFilters<Interactions>
protected abstract viewLogic(): ISubscription[]
private readonly _interactionSubjects: Subjects<Interactions> = createSubjects<Interactions>(this.interactionFilters)
protected readonly report: EventHandlers<Interactions> = generateHandlers<Interactions>(this._interactionSubjects)
protected readonly interactions: Observables<Interactions> =
filterInteractions<Interactions>(this._interactionSubjects, this.interactionFilters)
readonly context: undefined
constructor(props: Props) {
super(props)
}
componentWillMount(): void {
}
componentDidMount(): void {
}
componentWillReceiveProps(nextProps: Props): void {
}
shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
return true
}
componentWillUpdate(nextProps: Props, nextState: State): void {
}
componentDidUpdate(prevProps: Props, prevState: State): void {
}
componentWillUnmount() {
this._jobs.forEach(job => job.unsubscribe())
}
private _jobs: ISubscription[] = this.viewLogic()
}
type EventHandlers<Actions> = {[Name in keyof Actions]: EventHandler<Actions[Name]>}
type Observables<Actions> = {[Name in keyof Actions]: Observable<Actions[Name]>}
let generateHandlers = <Interactions>(subjects: Subjects<Interactions>): EventHandlers<Interactions> => {
let result: EventHandlers<Interactions> = {} as any
Object.keys(subjects).forEach(key => result[key] = (event: Interactions[typeof key]) => {
subjects[key].next(event)
})
return result
}
let filterInteractions = <Interactions>(subjects: Subjects<Interactions>,
filters: InteractionFilters<Interactions>): Observables<Interactions> => {
let result: Observables<Interactions> = {} as any
Object.keys(subjects).forEach(key => result[key] = subjects[key].let(filters[key]))
return result
}
export type InteractionFilters<Interactions> = {
[Key in keyof Interactions]: Mapper<Observable<Interactions[Key]>, Observable<Interactions[Key]>>
}
export let KeepOrigin = <T>(input: Observable<T>): Observable<T>=> input
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment