Skip to content

Instantly share code, notes, and snippets.

@tweinfeld
Created January 3, 2018 16:59
Show Gist options
  • Save tweinfeld/62f96732a65d7d81043ced7a1f01a9c2 to your computer and use it in GitHub Desktop.
Save tweinfeld/62f96732a65d7d81043ced7a1f01a9c2 to your computer and use it in GitHub Desktop.
An example of utilizing HTML5's History API in order to save and restore state. Whenever the state changes, a copy of it is stored in History whether it effected the URL route or not. It comes to demonstrate the somewhat concealed benefits of the History API.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/kefir@3.8.0/dist/kefir.min.js"></script>
<script src="https://unpkg.com/lodash@4.17.4/lodash.min.js"></script>
<script src="https://unpkg.com/react@16.2.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.2.0/umd/react-dom.development.js"></script>
</head>
<body>
<main/>
<script>
const
urlTemplate = ({ currentPage, currentItem })=> "/"+ _.compact([currentPage, currentPage === "item" && currentItem]).join('/'),
generateRandomState = (function(counter){
return ()=> ({
id: ++counter,
currentPage: _.sample(["welcome", "item"]),
currentItem: _.random(5, 1),
someRandomNumber: _.random(100),
someRandomAnimal: _.sample(["cat", "dog", "mouse"])
});
})(0);
let
statePushStream = Kefir.pool(),
applicationState = statePushStream.toProperty(),
activeUrlStream = applicationState.map(urlTemplate);
// Update address bar view (push)
applicationState
.sampledBy(activeUrlStream, (state, url)=> ({ ...state, _url: url }))
.onValue(({ _url, ...state })=> window.history[window.location.pathname !== _url ? "pushState" : "replaceState"](state, '', _url));
// Restore state back from address bar
Kefir
.fromEvents(window, 'popstate')
.map(()=> window.history.state)
.toProperty(()=> window.history.state || {})
.onValue((state)=> statePushStream.plug(Kefir.constant(state)));
// Update dom view
applicationState
.onValue((function(mainEl){
const [div, ul, li, button] = ["div", "ul", "li", "button"].map((tagName)=> _.partial(React.createElement, tagName));
return function({ someRandomAnimal, currentItem, currentPage, someRandomNumber }){
return ReactDOM.render(div({}, [], ...[
ul({}, [], ...[
li({}, `Page: ${currentPage}`),
li({}, `Item: ${currentItem}`),
li({}, `Animal: ${someRandomAnimal}`),
li({}, `Number: ${someRandomNumber}`)
]),
button({ onClick: ()=> statePushStream.plug(Kefir.constant(generateRandomState())) }, 'Generate Random State')
]), mainEl);
};
})(document.querySelector('main')));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment