choojs / choo

:steam_locomotive::train: - sturdy 4kb frontend framework

Home Page:https://choo.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Redirection to another during page load causes the view to not render.

mjstahl opened this issue · comments

Expected behavior

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

package.json

{
  "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"
  }
}

index.js

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')

Actual behavior

The actual result is:

Should NEVER get here.

And the route should be:

https://localhost:8080/login

Steps to reproduce behavior

Write here.

  1. Copy the above files into a folder
  2. npm i
  3. ./node_modules/.bin/bankai start index.js
  4. In a browser open, https://localhost:8080/

Notes

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?

views/protect.js

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)
  }
}

index.js

app.route('/home', protect(require('./views/home')))