choojs / choo

:steam_locomotive::train: - sturdy 4kb frontend framework
https://choo.io/
MIT License
6.78k stars 595 forks source link

Having issue with document title #554

Open hdriqi opened 7 years ago

hdriqi commented 7 years ago

I create an app with SSR with choo and expressjs.

So my template is using choo's html with full html tag, with head and body. In head tag, I create a title tag and yes it set up the title perfectly after SSR.

But, after I load the client-side bundle ( choojs ), the title in the tab is changed to undefined(localhost:xxxx). I already try changing it using document.title inside DOMContentLoaded but still no change in the title. I use state.title = xxx to inside it, but still no luck.

Anybody can give me an example of title changing in choojs?

brechtcs commented 7 years ago

So what you're trying to do is mounting your app on the <html> tag? For SSR, I tend to use basic template strings for the html boilerplate, and only use choo/html for stuff inside the <body> tag. Using choo/bel for the entire html document has caused me some issues before, so I tend to avoid that altogether.

lemmon commented 7 years ago

I use document.title = "My Page Title". Works just fine for me.

bcomnes commented 7 years ago

Also when interacting with global vars, https://www.npmjs.com/package/global can sometimes be handy for node/browser compatibility. I think @lemmon is correct though.

hdriqi commented 7 years ago

@brechtpm exactly, i mount choojs into html tag. I think splitting head and body is a good solution for now. thanks!

@lemmon where do you put that document.title syntax? inside an emitter?

@bcomnes i already use global but the title still empty string after i mount my template to html

bcomnes commented 7 years ago

@hdriqi I don't understand, are you calling document.title = "whatever" on the client at any point?

hdriqi commented 7 years ago

@bcomnes yes, i call it in my client bundle. So after SSR, the bundled JS is loaded. At this point the title that I already set in SSR head is changed into empty string.

lemmon commented 7 years ago

@hdriqi I update document.title inside any view function, whenever I want to change the title. I mount my app on a div inside the body tag so I don't overwrite the head.

yoshuawuyts commented 7 years ago

You want to be using the DOMTitlechange event, which was added in Choo v6. This will also play well with bankai's server rendering, setting the correct title in the initial HTML:

basic example:

function myView (state, emit) {
  emit('DOMTitleChange', 'welcome to my site!')
  return html`<body>hello</body>`
}

optimized example: This makes sure the string is only declared once, compresses better because state.events.DOMTITLECHANGE can be collapsed during minification, and only changes the title if it isn't already set, so re-renders won't cause extra noise.

var title = 'welcome to my site!'

function myView (state, emit) {
  if (state.title !== title) emit(state.events.DOMTITLECHANGE, title)
  return html`<body>hello</body>`
}

Hope this makes sense!