I am brand new to Choo so I may be thinking about this all wrong. But the use case is, the User comes to a route that requires authentication. They are not authenticated so they are routed to a login view at a different route.
I have written up a small Choo to make it easier to demostrate the problem. The expected result from the code below is:
Should ONLY EVER get here.
And the route should be:
https://localhost:8080/login
{
"name": "test-choo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bankai": "^9.14.0",
"choo": "^6.13.0"
}
}
const choo = require('choo')
const html = require('choo/html')
const app = choo()
app.use((state, emitter) => { state.session = null })
app.route('/', (state, emit) => {
if (!state.session) emit(state.events.REPLACESTATE, '/login')
return html`
<body>
<p>Should NEVER get here.</p>
</body>
`
})
app.route('/login', (state, emit) => {
return html`
<body>
<p>Should ONLY EVER get here.</p>
</body>
`
})
app.mount('body')
The actual result is:
Should NEVER get here.
And the route should be:
https://localhost:8080/login
Write here.
npm i./node_modules/.bin/bankai start index.jshttps://localhost:8080/What I noticed when tracing the function calls was that NAVIGATE event emitted and its callback executed.
In the start function (which was called after documentReady in mount), the RENDER event was never emitted because self._loaded was false (https://github.com/choojs/choo/blob/master/index.js#L101). After this code is executed, the documentReady callback in start is called, setting self._loaded to true.
So it appears that there is an order of operations issue maybe caused by the setTimeout in the documentReady call.
I would like to fix this problem (assuming its a problem), but I need a little bit of hand holding since I am only 1 day into Choo. Any guidance would be greatly appreciated.
Thanks for kareniel on IRC for the following snippet. I do think there could be a good way to work this into documentation. Maybe a tangent in the Forms documentation?
const login = require('./login');
module.exports = function protect (view) {
return function (state, emit) {
if (!state.isLoggedIn) {
emit(state.events.REPLACESTATE, '/login')
return login(state, emit)
}
return view(state, emit)
}
}
app.route('/home', protect(require('./views/home')))
Most helpful comment
Thanks for
karenielon IRC for the following snippet. I do think there could be a good way to work this into documentation. Maybe a tangent in theFormsdocumentation?views/protect.js
index.js