Skip to content

Instantly share code, notes, and snippets.

@yelouafi
Last active September 27, 2017 09:13
Show Gist options
  • Save yelouafi/0385402a453b1fdb5cb0 to your computer and use it in GitHub Desktop.
Save yelouafi/0385402a453b1fdb5cb0 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Redux rocket launcher example</title>
<script src="https://npmcdn.com/redux@latest/dist/redux.min.js"></script>
<script src="https://npmcdn.com/redux-saga@0.9.1/dist/redux-saga.js"></script>
</head>
<body>
<p>
Example created to compare Redux + redux-saga implementation with
<a href="http://jdubray.github.io/sam/" target="_blank">SAM</a> implementation
<br>
SAM implementation can be found <a href="https://bitbucket.org/snippets/jdubray/9dgKp/sam-sample" target="_blank">here</a>
</p>
<hr>
<div id="app"></div>
<script>
"use strict"
const extend = (state, ext) => Object.assign({}, state, ext)
//////////////////////////////////////////////////////////////////////////
//
// Reducers
//
const COUNTER_MAX = 10 ;
var initialState = {
counter: COUNTER_MAX,
started: false,
launched: false,
aborted: false
}
function reducer(state, action) {
if(state === undefined)
return initialState
switch (action.type) {
case 'START':
return extend(initialState, { counter: COUNTER_MAX, started: true })
case 'DECREMENT':
return extend(state, { counter: state.counter - 1 })
case 'ABORT':
return extend(state, { started: false, aborted: true })
case 'LAUNCH':
return extend(state, { started: false, launched: true })
default:
return state
}
}
//////////////////////////////////////////////////////////////////////////
//
// Sagas
//
const io = ReduxSaga.effects
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
function* rocketLauncherSaga() {
yield io.take('START')
for(let i = 0; i < COUNTER_MAX; i++) {
const winner = yield io.race({
decrement: io.call(delay, 1000),
abort : io.take('ABORT')
})
if(winner.abort)
return
yield io.put({type: 'DECREMENT'})
}
yield io.put({type: 'LAUNCH'})
}
//////////////////////////////////////////////////////////////////////////
//
// View
//
const renderCounting = (model) => (`
<p>Counter ${model.started ? "down" : ""} : ${model.counter}</p>
<form onSubmit="JavaScript:return actions.${model.started ? "abort()" : "start()"};">
<input type="submit" value="${model.started ? "Abort" : "Start"}">
</form>
`)
const renderAborted = (model) => `<p>Aborted at Counter: ${model.counter}</p>`
const renderLaunched = (model) => (`<p>Launched</p>`)
const renderMain = (model) => (
model.launched ? renderLaunched(model)
: model.aborted ? renderAborted(model)
: renderCounting(model)
)
////////////////////////////////////////////////////////////////
//
// actions
//
const formAction = type => {
store.dispatch({type: type})
return false
}
const actions = {
start: () => formAction('START'),
abort: () => formAction('ABORT')
}
////////////////////////////////////////////////////////////////
//
// Setup
//
const createSagaMiddleware = ReduxSaga.default
var store = Redux.createStore(
reducer,
Redux.applyMiddleware(createSagaMiddleware(rocketLauncherSaga))
)
var el = document.getElementById("app");
function display() {
el.innerHTML = renderMain(store.getState())
}
store.subscribe(() => display())
display()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment