navi icon indicating copy to clipboard operation
navi copied to clipboard

route's title does not work

Open linlycode opened this issue 5 years ago • 10 comments

I have the following routes:

mount({
	'/': route({
		title: 'Home',
		view: <Home />,
	}),
	'/about': route({
		title: 'About',
		view: <About />,
	}),
}))

but as it renders, the title of the browser tab is not set, is it expected behavior? I'm not using react-helmet and static rendering

Do I need to use react-helmet for it to work?

linlycode avatar Jul 19 '19 04:07 linlycode

The behavior here has changed in 0.13 (which was released a few minutes ago).

In 0.12, it should have worked automatically, although this prevented people from integrating Navi with react-helmet or react-helmet-async.

In 0.13, you'll need to add react-navi-helmet-async (or react-navi-helmet) and wrap your app with the exported provider:

ReactDOM.render(
  <HelmetProvider>
    <Router routes={routes}>
      ...
    </Router>
  </HelmetProvider>,
  document.getElementById('root')
)

See more details here: https://frontarm.com/navi/en/guides/setting-head-meta-title/

jamesknelson avatar Jul 19 '19 04:07 jamesknelson

The behavior here has changed in 0.13 (which was released a few minutes ago).

In 0.12, it should have worked automatically, although this prevented people from integrating Navi with react-helmet or react-helmet-async.

In 0.13, you'll need to add react-navi-helmet-async (or react-navi-helmet) and wrap your app with the exported provider:

ReactDOM.render(
  <HelmetProvider>
    <Router routes={routes}>
      ...
    </Router>
  </HelmetProvider>,
  document.getElementById('root')
)

See more details here: https://frontarm.com/navi/en/guides/setting-head-meta-title/

Thanks, it's working now.

I noticed the doc has changed, so if I read the doc a few hours later there'd be no problem, that timing... :joy:

linlycode avatar Jul 19 '19 05:07 linlycode

Glad that it works 😆. I'll leave this one open for a little while just in case anyone else runs into the same issue.

jamesknelson avatar Jul 19 '19 05:07 jamesknelson

May I ask what is the benefit of a custom abstraction over rendering react-helmet in the children of a mounted route component? At first glance that would produce an identical result.

kettanaito avatar Jul 19 '19 10:07 kettanaito

@kettanaito the main benefit for setting the title with Navi is that it's just a plain string, and can be accessed anywhere by checking useCurrentRoute().title. It also helps for integration with static/server rendering.

I'm not sure there is really much benefit over that though. I'd actually like to get rid of head/title support from Navi core at some point. This is the first step in that direction, given that Navi no longer actually sets document.title by default.

jamesknelson avatar Jul 19 '19 12:07 jamesknelson

I wouldn't let routing decide that. It falls out of its responsibility, imho. Instead, any rendered component (view) can render things that affect page's title and other attributes. react-helmet, for instance, allows to control per-component title, meta, body and other attributes.

Those solutions usually provide API for server-side rendering. I'm brining this because it feels it would be too much for Navi to handle.

kettanaito avatar Jul 19 '19 13:07 kettanaito

I agree, although for backwards compatibility at least it needs to be there for now (Navi has rendered page title since it's first release - this is actually the first release that doesn't do it out of the box).

For what it's worth, I'm not 100% convinced that components are the right place for titles either, though. When doing SSR, you get a 1:1 mapping of URLs to page titles, so part of me still thinks it should be the router's job.

jamesknelson avatar Jul 19 '19 13:07 jamesknelson

I think it's fine to let the router manage the title, router is responsible for rendering pages, title is a page property, so why not?

And I definitely wouldn't like to manage titles in components, components are meant to be reused, composed, so it's better to keep them away from global stuff and free from side effects.

Thus, I prefer letting the router do it. Anyway It's just my opinion.

linlycode avatar Jul 19 '19 16:07 linlycode

The page components you render are usually not reusable, as they are specific to the context (i.e route) they are rendered in. It's perfectly fine to set titles in them using both ways we've mentioned.

My main concern goes to the responsibilities separation. Routing ensures that a certain content is resolved depending on a URL:

url -- router --> content

A page's title is, like you've mentioned, a page (content) property. That's why I would expect to manage it once I'm in the page's context, which means after the page component has mounted:

url -- router --> content --> setTitle('foo')

Yet if Navi manages the title, I start to expect it to manage it even after the page's mount. Suddenly, it becomes one of the features of the package that requires maintenance.

# Now I expect Navi to keep managing title
# since it's done that at the first place
url --> router --> setTitle('foo') --> content --> navi.setTitle('foo')

The less responsibilities your implementation has, the more composable it becomes. I'm not directly against Navi controlling the title, but I think this feature doesn't belong into the core functionality. It can, however, be extended on demand with an additional package (i.e. react-navi-helmet-async).

kettanaito avatar Jul 19 '19 16:07 kettanaito

@kettanaito good points.

I just feel it's convenient to declare the title along with routes, since titles are usually fixed for each page. Another obvious benefit is that I can see the title without going into the components.

And I still think managing titles in components feels weird because the component is affecting something outside of it's node, this means there are implicit dependencies and once they are not present the component breaks, and to know the dependencies you have to look at the implementation.

linlycode avatar Jul 19 '19 17:07 linlycode