How to label each page with a title?

This may seem a trivial thing – and maybe it is – but please bear with me (as I have very little experience with Solid yet). I have a Solid app. It has a routes.tsx file which defines routes – a nested array of RouteDefinition. Then I have this:
render(() => (
<Router root={Layout}>
{routes}
</Router>
), document.getElementById('app')!);
render(() => (
<Router root={Layout}>
{routes}
</Router>
), document.getElementById('app')!);
Not surprisingly, the Layout component has a Header component, which renders a title. Now, here is a question: what is a canonical/best/sensible way for any of the components in routes to tell Header in Layout what the title of the current "screen" is? Related question: I'd also like the <title> tag to be dynamically set depending on the current "screen" (possibly to the same value as the one in the header). How to achieve that?
8 Replies
peerreynders
peerreynders2mo ago
Solid Meta's Title component.
mbork.pl
mbork.pl2mo ago
Thanks! Do I get it right that this could solve the <title> tag issue? What about the other one?
peerreynders
peerreynders2mo ago
depending on the current "screen"
- if I understand what you are trying to achieve - and if I recall correctly <Title> operates on a “last one in the document flow” wins basis, so if you adopt a convention of always specifying a <Title> within the route component you should get the “screen” functionality which still can be overridden by a nested route/component. Though you seem to want to access the currently active title in the header...
mbork.pl
mbork.pl2mo ago
exactly, that's the point right now, the only way I know of accessing the title in <Header> is to keep it in a context object and setting it in every component, which works, but doesn't seem ideal...
peerreynders
peerreynders2mo ago
Meta's job is to collect all the relevant information so that it can render the tags in the document header. Right now I don't see a means of accessing the final title content. So what doesn't seem ideal to you about keeping it in a context?
mbork.pl
mbork.pl2mo ago
Here's an example. If a user tries to access a route they don't have permission to access, the component (which normally sets the title in the context) is not rendered at all (and rightly so). But that means that the user sees a "placeholder component" (which is basically a box saying "You are not permitted to see this") together with a wrong title (because the piece of code which actually sets the header is never reached). I could circumvent this by calling that "not permitted" component inside each and every page component, but that is also not good (obviously), since it heavily violates the DRY principle.
peerreynders
peerreynders2mo ago
The only thing I might do is “split-the-hook” in order to preserve read-write segregation. It only operates on the TypeScript level so there shouldn't be any overhead. Though in your case you probably want to create a component that uses the “write title hook” which can then be conveniently used inside the route components to override the title. Then the header uses the “read title hook” to obtain it, uses the content in it's JSX and set the Meta <Title> component.
GitHub
solid-start-notes-basic/src/components/app-context.tsx at f13872d00...
Basic client rendered notes app using SolidStart beta - peerreynders/solid-start-notes-basic
peerreynders
peerreynders2mo ago
together with a wrong title
Wouldn't the place holder component set the title? … given it's a route level 401 So I'd be inclined to force <Navigate> (or useNavigate()) to a 401 route anyway.