Last active
May 21, 2016 16:18
-
-
Save lewtds/9b5e5c7e6fd7258d2ebc4e5eb453b205 to your computer and use it in GitHub Desktop.
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
// @flow | |
import React from 'react'; | |
import { Updater, view as viewWrapper } from 'redux-elm'; | |
import { takeEvery, takeLatest } from 'redux-saga'; | |
import { call, put, fork, cancel, take, race } from 'redux-saga/effects'; | |
import run from './boilerplate'; | |
type State = { | |
count: number, | |
running: boolean, | |
}; | |
function initialState(): State { | |
return { | |
count: 10, | |
running: false | |
}; | |
} | |
const updater = new Updater(initialState(), worker) | |
.case('START_TIMER', handle_start) | |
.case('TIMER_STOPPED', handle_stop) | |
.case('UP', handle_up) | |
.case('DOWN', handle_down) | |
.toReducer(); | |
function handle_start(model) { | |
return {...model, running: true}; | |
} | |
function handle_stop(model) { | |
return {...model, running: false}; | |
} | |
function handle_up(model: State): State { | |
return {...model, count: model.count + 1}; | |
} | |
function handle_down(model: State): State { | |
return {...model, count: model.count - 1}; | |
} | |
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); | |
function* runTimer() { | |
while (true) { | |
yield call(delay, 500); | |
yield put({type: 'UP'}); | |
} | |
} | |
function* worker() { | |
while (true) { | |
// take = blockingly wait for the specified event | |
yield take('START_TIMER'); | |
// once the first task of the two finishes, the other task will be canceled. | |
yield race({ | |
timerTask: call(runTimer), | |
cancel: take('STOP_TIMER'), | |
}); | |
yield put({type: 'TIMER_STOPPED'}); | |
} | |
} | |
const startButton = (dispatch) => | |
<button onClick={dispatch.bind(null, {type: 'START_TIMER'})}>START</button>; | |
const stopButton = (dispatch) => | |
<button onClick={dispatch.bind(null, {type: 'STOP_TIMER'})}>STOP</button>; | |
const view = viewWrapper(({model: {count, running}, dispatch}) => { | |
return ( | |
<div> | |
{(running ? stopButton : startButton)(dispatch)} | |
{count} | |
</div> | |
); | |
}); | |
run('app', view, updater); |
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 React from 'react'; | |
import { render } from 'react-dom'; | |
import { createStore, compose } from 'redux'; | |
import { Provider, connect } from 'react-redux'; | |
import reduxElm from 'redux-elm'; | |
export default (containerDomId, View, updater) => { | |
const storeFactory = compose( | |
reduxElm, | |
window.devToolsExtension ? window.devToolsExtension() : f => f | |
)(createStore); | |
const store = storeFactory(updater); | |
const ConnectedView = connect(appState => ({ | |
model: appState | |
}))(View); | |
render(( | |
<Provider store={store}> | |
<ConnectedView /> | |
</Provider> | |
), document.getElementById(containerDomId)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment