Skip to content

Instantly share code, notes, and snippets.

@alanrsoares
Created June 21, 2017 02:53
Show Gist options
  • Save alanrsoares/f3b77d60ed8432dbd50c1d189e578f1a to your computer and use it in GitHub Desktop.
Save alanrsoares/f3b77d60ed8432dbd50c1d189e578f1a to your computer and use it in GitHub Desktop.
class Observable {
constructor(value) {
this.value = value
this.events = { change: [] }
}
update(updateFn) {
this.value = updateFn(this.value)
this.events.change.forEach(fn => fn(this.value))
}
onChange(fn) {
this.events.change.push(fn)
}
}
class Store extends Observable {
constructor(reducer) {
super(reducer())
this.reducer = reducer
}
dispatch(action) {
this.update(state => this.reducer(state, action))
}
}
class Connect {
constructor(props) {
this.props = props
this.state = props.store.value
this.props.store.onChange(storeState => {
this.state = storeState
this.render()
})
}
render() {
const Component = this.props.component
return new Component(this.props.mapStateToProps(this.state)).render()
}
}
const Provider = store => component => props =>
new component({ ...props, store })
const connect = mapStateToProps => component => props =>
new Connect({ ...props, component, mapStateToProps })
// app code
const actionTypes = {
INC: 'INC',
DEC: 'DEC'
}
const actions = {
inc: () => ({ type: actionTypes.INC }),
dec: () => ({ type: actionTypes.DEC })
}
const initialState = { timeElapsed: 0 }
const rootReducer = (state = initialState, action = {}) => {
switch(action.type) {
case actionTypes.INC:
return ({ timeElapsed: state.timeElapsed + 1 })
case actionTypes.DEC:
return ({ timeElapsed: state.timeElapsed - 1 })
default:
return state
}
}
const store = new Store(rootReducer)
class App {
constructor(props) {
this.props = props
}
render() {
const template = `time elapsed: ${this.props.timeElapsed} seconds`
document.getElementById('app').innerHTML = template
}
}
const connected = connect(x => x)(App)
const ProvidedApp = Provider(store)(connected)
const app = new ProvidedApp()
app.render()
const incrementTimer = () => store.dispatch(actions.inc())
const decrementTimer = () => store.dispatch(actions.dec())
setInterval(incrementTimer, 1000)
setInterval(decrementTimer, 5000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment