Last active
November 2, 2017 23:42
-
-
Save kakajika/2e43244ff51fb3ec2c88ada0b3ed4041 to your computer and use it in GitHub Desktop.
Simple type-safe flux implementation with RxJS & TypeScript. Inspired by flumpt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react" | |
import * as Rx from "rxjs" | |
export class Action<T> { | |
constructor(public key: string) {} | |
} | |
interface FluxContext { | |
dispatch: <T extends any>(action: Action<T>, value: T) => void | |
} | |
export class Flux<State> extends React.Component<void, State> { | |
private subjects: { [key: string]: Rx.Subject<any> } = {} | |
on = <T extends any>(action: Action<T>, dispatcher: (value: T) => void) => { | |
const subject = new Rx.Subject<T>() | |
this.subjects[action.key] = subject | |
subject.subscribe(dispatcher) | |
} | |
static childContextTypes = { | |
dispatch: React.PropTypes.func | |
} | |
getChildContext(): FluxContext { | |
return { | |
dispatch: <T extends any>(action: Action<T>, value: T) => { | |
if (this.subjects[action.key]) { | |
this.subjects[action.key].next(value) | |
} | |
} | |
} | |
} | |
} | |
export class Component<Props, State> extends React.Component<Props, State> { | |
static contextTypes = { | |
dispatch: React.PropTypes.func | |
} | |
context: FluxContext | |
dispatch = this.context.dispatch | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Flux, Action, Component} from ".flux" | |
const IncrementAction = new Action<void>("increment") | |
interface State { | |
count: number | |
} | |
class App extends Flux<State> { | |
state: State = { | |
count: 0 | |
} | |
componentDidMount() { | |
this.on(IncrementAction, () => { | |
this.setState({ count: this.state.count + 1 }) | |
}) | |
} | |
render() { | |
return <MyComponent {...this.state}/> | |
} | |
} | |
class MyComponent extends Component<State, {}> { | |
render() { | |
return ( | |
<div> | |
{this.props.count} | |
<button onClick={() => this.dispatch(IncrementAction)}>increment</button> | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment