Created
October 20, 2017 12:49
-
-
Save selfup/7f2d912f37f8d0190594b72aa47bbdb7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { app } from 'hyperapp' | |
import { main, nav, section, h1, button, a, p, span } from '@hyperapp/html' | |
const Route = props => { | |
const match = props.exact | |
? location.pathname === props.path | |
: location.pathname.match(props.path) | |
return props.render | |
? match && props.render({ path: props.path }) | |
: match && section(props.view) | |
} | |
const Redirect = props => { | |
// You can resolve the skipped render by triggering the update on the next tick | |
// but you do see a flash of guarded content | |
props.when && history.replaceState(null, null, props.to) | |
// props.when && setTimeout(() => history.replaceState(null, null, props.to), 0) | |
} | |
const Home = [h1('Home Page')] | |
const Login = [h1('Login Page')] | |
const Todos = [h1('Todos Page')] | |
const Todo = [h1('Todo Page')] | |
app({ | |
state: {}, | |
actions: { | |
update: () => { | |
console.log('Updating state path to', location.pathname) | |
return { path: location.pathname } | |
}, | |
auth: () => ({ user: 'Joe Bloggs' }), | |
deauth: () => ({ user: null }), | |
rerender: () => ({ rand: Math.random() }), | |
}, | |
view: (state, actions) => | |
main([ | |
nav([ | |
a({ href: '/' }, 'Home'), | |
a({ href: '/login' }, 'Login'), | |
a({ href: '/todos' }, 'Todos'), | |
a({ href: '/todos/1' }, 'Todo'), | |
button({ onclick: actions.auth }, 'AUTH'), | |
button({ onclick: actions.deauth }, 'DEAUTH'), | |
state.user && p(`Logged in as ${state.user}`), | |
]), | |
Route({ exact: true, path: '/', view: Home }), | |
Route({ exact: true, path: '/login', view: Login }), | |
Route({ | |
path: '/todos', | |
render: () => [ | |
Redirect({ to: '/login', when: !state.user }), | |
span([ | |
p(` | |
You shouldnt see me if you arent authed. | |
Redirect should have called history.replaceState which calls update. | |
You can see that the window pathname ${location.pathname} and state path ${state.path} are equal. | |
But you will not see the represented in the view until you call another action. | |
Or use setTimout on the update, or remove skipRender from hyperapp core. | |
`), | |
button( | |
{ onclick: actions.rerender }, | |
'Trigger a re-render (random action)' | |
), | |
]), | |
Route({ exact: true, path: '/todos', view: Todos }), | |
Route({ path: '/todos/1', view: Todo }), | |
], | |
}), | |
]), | |
init: (state, actions) => { | |
// Calling pushstate triggers a state update | |
var pushState = history.pushState | |
history.pushState = function() { | |
pushState.apply(history, arguments) | |
actions.update() | |
} | |
// Calling replaceState triggers a state update | |
var replaceState = history.replaceState | |
history.replaceState = function() { | |
replaceState.apply(history, arguments) | |
actions.update() | |
} | |
// Listen to clicks on links and call pushstate | |
addEventListener('click', e => { | |
const link = e.target.tagName === 'A' | |
const path = e.target.getAttribute('href') | |
if (link && path && path.startsWith('/')) { | |
history.pushState(null, null, path) | |
e.preventDefault() | |
} | |
}) | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment