I’m trying to synchronize browser history with state contained within an onionify state store in a very simple cycle js example application. I have no problem mapping from state store to history, the issue is in reducing history.state back into the state store. Essentially, I get caught in an infinity loop of state streams flowing into one another, this crashes the browser.
import { run } from "@cycle/run";
import { div, button, p, makeDOMDriver } from "@cycle/dom";
import onionify from "cycle-onionify";
import { makeHistoryDriver } from "@cycle/history";
import xs from "xstream";
const main = (sources) => {
const popHistory$ = sources.history; // This is the problem...
const action$ = xs.merge(
sources.DOM.select(".decrement").events("click").map( () => -1 ),
sources.DOM.select(".increment").events("click").map( () => +1 ),
);
const state$ = sources.onion.state$;
const vdom$ = state$.map( state =>
div([
button(".decrement", "Decrement"),
button(".increment", "Increment"),
p(`Count: ${state.count}`)
])
);
const initReducer$ = xs.of( function initReducer() {
return {count: 0};
});
const updateReducer$ = action$.map( x => function reducer(prevState) {
return {count: prevState.count + x};
});
// this is where the inifinity loop starts
const historyReducer$ = popHistory$.map( history => function(prevState) {
return {count: history.state.count};
});
// You can't merge historyReducer$ here
const reducer$ = xs.merge(initReducer$, updateReducer$, historyReducer$);
const pushHistory$ = state$.map( state => ({
type: "push",
pathname: `/?count=${state.count}`,
state: state
}));
return {
DOM: vdom$,
onion: reducer$,
history: pushHistory$,
debug: popHistory$
}
};
const onionMain = onionify(main);
run(onionMain, {
DOM: makeDOMDriver("#main"),
history: makeHistoryDriver(),
debug: $ => $.subscribe({next: console.log})
});
I guess my question is: is there an easier way to do this?. Is there an operator that helps here? I feel like what I'm trying to do is fundamentally impossible. Any answers or links to useful resources would be appreciated.