Skip to content

Instantly share code, notes, and snippets.

@olpeh
Created October 10, 2017 19:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olpeh/3edb1ab8bc93a7442559a6efb988c5bb to your computer and use it in GitHub Desktop.
Save olpeh/3edb1ab8bc93a7442559a6efb988c5bb to your computer and use it in GitHub Desktop.
Cycle.js state management example
import xs from "xstream";
import { run } from "@cycle/run";
import {
makeDOMDriver,
h1,
h4,
div,
select,
option,
span,
input
} from "@cycle/dom";
import onionify from "cycle-onionify";
function renderOption(currency, selectedCurrency) {
return currency === selectedCurrency
? option(
{
attrs: {
selected: "selected"
}
},
[currency]
)
: option([currency]);
}
function intent(DOMSource) {
const currencyChangeAction$ = DOMSource.select(".currency")
.events("input")
.map(ev => ({
type: "CURRENCY_CHANGE",
payload: ev.target.value
}));
const priceInputAction$ = DOMSource.select(".price")
.events("input").debug()
.map(ev => ({
type: "PRICE_INPUT",
payload: ev.target.value
}));
return xs.merge(currencyChangeAction$, priceInputAction$);
}
function model(action$) {
const initReducer$ = xs.of(function initReducer(prevState) {
// Note that we ignore the prevState argument given,
// since it's probably undefined anyway
return { currency: "€", price: 100 }; // this is the initial state
});
const currencyChangeReducer$ = action$
.filter(ac => ac.type === "CURRENCY_CHANGE")
.map(
ac =>
function currencyChangeReducer(prevState) {
return {
...prevState,
currency: ac.payload
};
}
);
const priceInputReducer$ = action$
.filter(ac => ac.type === "PRICE_INPUT")
.map(
ac =>
function priceInputReducer(prevState) {
return {
...prevState,
price: ac.payload
};
}
);
return xs.merge(initReducer$, currencyChangeReducer$, priceInputReducer$);
}
function view(state$) {
return state$.map(state =>
div([
h1("Cycle.js simple example"),
span("Select currency"),
select(".currency", [
renderOption("€", state.currency),
renderOption("$", state.currency),
renderOption("¥", state.currency)
]),
div([
span("Set a price"),
input(".price", {
attrs: {
type: "number",
min: 0,
value: state.price
}
})
]),
div(".result", [
h4(`Now you have selected: ${state.price}${state.currency}`)
])
])
);
}
function main(sources) {
const state$ = sources.onion.state$;
const action$ = intent(sources.DOM);
const reducer$ = model(action$);
const vdom$ = view(state$);
const sinks = {
DOM: vdom$,
onion: reducer$
};
return sinks;
}
const drivers = {
DOM: makeDOMDriver("#app")
};
const wrappedMain = onionify(main);
run(wrappedMain, drivers);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment