Skip to content

Instantly share code, notes, and snippets.

@tecsyscom
Created April 15, 2017 06:04
Show Gist options
  • Save tecsyscom/76bc8a4f7a20d1db23fbc43e647b2aee to your computer and use it in GitHub Desktop.
Save tecsyscom/76bc8a4f7a20d1db23fbc43e647b2aee to your computer and use it in GitHub Desktop.
JS Bin // source https://jsbin.com/bomugapuxi
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="https://fb.me/react-0.14.0.min.js"></script>
<script src="https://fb.me/react-dom-0.14.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.min.js"></script>
<script src="https://npmcdn.com/xstream@9.0.0/dist/xstream.min.js"></script>
<script src="https://npmcdn.com/@cycle/xstream-run@4.0.0/dist/cycle.min.js"></script>
<script>
const xs = xstream.default;
function createCycleMiddleware () {
let store = null;
let actionListener = null;
let stateListener = null;
const cycleMiddleware = _store => {
store = _store;
return next => {
return action => {
let result = next(action)
if (actionListener) {
actionListener.next(action);
}
if (stateListener) {
stateListener.next(store.getState());
}
return result
}
}
}
cycleMiddleware.makeActionDriver = () => {
return function actionDriver(outgoing$) {
outgoing$.addListener({
next: outgoing => {
if (store) {
store.dispatch(outgoing);
}
},
error: () => {},
complete: () => {},
});
return xs.create({
start: listener => {
actionListener = listener;
},
stop: () => {},
});
}
}
cycleMiddleware.makeStateDriver = () => {
const isSame = {};
const getCurrent = store.getState;
return function stateDriver() {
return xs.create({
start: listener => {
stateListener = listener;
},
stop: () => {},
})
.fold((prevState, currState) => {
if (prevState === getCurrent) {
prevState = getCurrent();
}
if (prevState === currState) {
return isSame;
}
return currState;
}, getCurrent)
.map(state => state === getCurrent ? getCurrent() : state)
.filter(state => state !== isSame);
}
}
return cycleMiddleware;
}
</script>
</head>
<body>
<div id='root'></div>
<script id="jsbin-javascript">
'use strict';
function main(sources) {
var increment$ = sources.ACTION.filter(function (action) {
return action.type === 'INCREMENT_ASYNC';
}).mapTo({ type: 'INCREMENT' });
var decrement$ = sources.ACTION.filter(function (action) {
return action.type === 'DECREMENT_ASYNC';
}).mapTo({ type: 'DECREMENT' });
var both$ = xs.merge(increment$, decrement$).map(function (d) {
return xs.periodic(500) // async
.take(1).mapTo(d);
}).flatten();
return {
ACTION: both$
};
}
/*
* How is the next application state calculated,
* given the current state and the action?
*/
var counter = function counter(state, action) {
if (state === undefined) state = 0;
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
/*
* What does UI look like, assuming it doesn't know
* about the state or actions, and is a function
* of the props?
*/
var Counter = function Counter(_ref) {
var value = _ref.value;
var onIncrement = _ref.onIncrement;
var onDecrement = _ref.onDecrement;
return React.createElement(
'div',
null,
React.createElement(
'h1',
null,
value
),
React.createElement(
'button',
{ onClick: onIncrement },
'+'
),
React.createElement(
'button',
{ onClick: onDecrement },
'-'
)
);
};
/*
* Which injected props should be calculated
* from the application state and how?
*/
var mapStateToProps = function mapStateToProps(state) {
return {
value: state
};
};
/*
* Which injected props should be callbacks
* that dispatch actions, and which actions?
*/
var mapDispatchToProps = function mapDispatchToProps(dispatch) {
return {
onIncrement: function onIncrement() {
dispatch({
type: 'INCREMENT_ASYNC'
});
},
onDecrement: function onDecrement() {
dispatch({
type: 'DECREMENT_ASYNC'
});
}
};
};
/*
* Let's create a container component
* that injects props into the pure UI component
* according to the instructions above, but
* instead of all those props, accepts a store.
*/
var _ReactRedux = ReactRedux;
var connect = _ReactRedux.connect;
var CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter);
/*
* Let's create a store.
*/
var _Redux = Redux;
var createStore = _Redux.createStore;
var applyMiddleware = _Redux.applyMiddleware;
var cycleMiddleware = createCycleMiddleware();
var makeActionDriver = cycleMiddleware.makeActionDriver;
var store = createStore(counter, applyMiddleware(cycleMiddleware));
Cycle.run(main, {
ACTION: makeActionDriver()
});
/*
* Finally, render the container,
* passing the store to it.
*/
ReactDOM.render(React.createElement(CounterContainer, { store: store }), document.getElementById('root'));
</script>
<script id="jsbin-source-javascript" type="text/javascript">
function main(sources) {
const increment$ = sources.ACTION
.filter(action => action.type === 'INCREMENT_ASYNC')
.mapTo({ type: 'INCREMENT' });
const decrement$ = sources.ACTION
.filter(action => action.type === 'DECREMENT_ASYNC')
.mapTo({ type: 'DECREMENT' });
const both$ = xs.merge(increment$, decrement$)
.map(d =>
xs.periodic(500) // async
.take(1)
.mapTo(d)
)
.flatten();
return {
ACTION: both$
}
}
/*
* How is the next application state calculated,
* given the current state and the action?
*/
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
/*
* What does UI look like, assuming it doesn't know
* about the state or actions, and is a function
* of the props?
*/
const Counter = ({
value,
onIncrement,
onDecrement
}) => (
<div>
<h1>{value}</h1>
<button onClick={onIncrement}>+</button>
<button onClick={onDecrement}>-</button>
</div>
);
/*
* Which injected props should be calculated
* from the application state and how?
*/
const mapStateToProps = (state) => {
return {
value: state
};
}
/*
* Which injected props should be callbacks
* that dispatch actions, and which actions?
*/
const mapDispatchToProps = (dispatch) => {
return {
onIncrement: () => {
dispatch({
type: 'INCREMENT_ASYNC'
})
},
onDecrement: () => {
dispatch({
type: 'DECREMENT_ASYNC'
})
}
};
};
/*
* Let's create a container component
* that injects props into the pure UI component
* according to the instructions above, but
* instead of all those props, accepts a store.
*/
const { connect } = ReactRedux;
const CounterContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
/*
* Let's create a store.
*/
const { createStore, applyMiddleware } = Redux;
const cycleMiddleware = createCycleMiddleware();
const { makeActionDriver } = cycleMiddleware;
const store = createStore(
counter,
applyMiddleware(cycleMiddleware)
);
Cycle.run(main, {
ACTION: makeActionDriver()
})
/*
* Finally, render the container,
* passing the store to it.
*/
ReactDOM.render(
<CounterContainer store={store} />,
document.getElementById('root')
);</script></body>
</html>
'use strict';
function main(sources) {
var increment$ = sources.ACTION.filter(function (action) {
return action.type === 'INCREMENT_ASYNC';
}).mapTo({ type: 'INCREMENT' });
var decrement$ = sources.ACTION.filter(function (action) {
return action.type === 'DECREMENT_ASYNC';
}).mapTo({ type: 'DECREMENT' });
var both$ = xs.merge(increment$, decrement$).map(function (d) {
return xs.periodic(500) // async
.take(1).mapTo(d);
}).flatten();
return {
ACTION: both$
};
}
/*
* How is the next application state calculated,
* given the current state and the action?
*/
var counter = function counter(state, action) {
if (state === undefined) state = 0;
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
/*
* What does UI look like, assuming it doesn't know
* about the state or actions, and is a function
* of the props?
*/
var Counter = function Counter(_ref) {
var value = _ref.value;
var onIncrement = _ref.onIncrement;
var onDecrement = _ref.onDecrement;
return React.createElement(
'div',
null,
React.createElement(
'h1',
null,
value
),
React.createElement(
'button',
{ onClick: onIncrement },
'+'
),
React.createElement(
'button',
{ onClick: onDecrement },
'-'
)
);
};
/*
* Which injected props should be calculated
* from the application state and how?
*/
var mapStateToProps = function mapStateToProps(state) {
return {
value: state
};
};
/*
* Which injected props should be callbacks
* that dispatch actions, and which actions?
*/
var mapDispatchToProps = function mapDispatchToProps(dispatch) {
return {
onIncrement: function onIncrement() {
dispatch({
type: 'INCREMENT_ASYNC'
});
},
onDecrement: function onDecrement() {
dispatch({
type: 'DECREMENT_ASYNC'
});
}
};
};
/*
* Let's create a container component
* that injects props into the pure UI component
* according to the instructions above, but
* instead of all those props, accepts a store.
*/
var _ReactRedux = ReactRedux;
var connect = _ReactRedux.connect;
var CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter);
/*
* Let's create a store.
*/
var _Redux = Redux;
var createStore = _Redux.createStore;
var applyMiddleware = _Redux.applyMiddleware;
var cycleMiddleware = createCycleMiddleware();
var makeActionDriver = cycleMiddleware.makeActionDriver;
var store = createStore(counter, applyMiddleware(cycleMiddleware));
Cycle.run(main, {
ACTION: makeActionDriver()
});
/*
* Finally, render the container,
* passing the store to it.
*/
ReactDOM.render(React.createElement(CounterContainer, { store: store }), document.getElementById('root'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment