Skip to content

W0703: A layout reading the request ​

A folder's layout stays while the visitor moves between the pages below it: its Load doesn't run again, and its sidebar keeps its scroll, its menus their state. That holds for a layout reading only its path parameters, which can't change under it. One whose methods — or the functions of its package they call — read more of the request, web.Request(ctx), an *http.Request, its URL or query, could show something stale, so it loads and renders again on every navigation, as vuka registers it (web.ReloadLayout). It works; it is only slower, and what it renders doesn't stay.

The usual reason is a menu marking the current page. Mark it in the browser instead, with ui.Link's active: the runtime follows the address on every navigation.

The other is a header showing the page's title or breadcrumbs, read in the layout's Load with ui.PageTitle(ctx) or ui.PageCrumbs(ctx). A Load that runs once would keep the first page's, so the layout reloads too. Read them in the markup instead: it renders again for every page while the layout stays.

Wrong ​

html
<script lang="go">
// pages/_layout.vuka.html
type Layout struct {
	Children ui.Node
	path     string
}

func (l *Layout) Load(ctx context.Context) error {
	l.path = web.Request(ctx).URL.Path
	return nil
}
</script>

<nav>
  if strings.HasPrefix(path, "/orders") {
    <a href="/orders" class="on">Orders</a>
  } else {
    <a href="/orders">Orders</a>
  }
</nav>
<main>{Children}</main>
html
<script lang="go">
// pages/_layout.vuka.html
type Layout struct {
	Children ui.Node
}
</script>

<nav>
  <ui.Link href="/orders" active="prefix" activeClass="on">Orders</ui.Link>
</nav>
<main>{Children}</main>

Wrong: the title in Load ​

html
<script lang="go">
// pages/admin/_layout.vuka.html
type Shell struct {
	Children ui.Node
	title    string
}

func (l *Shell) Load(ctx context.Context) error {
	l.title = ui.PageTitle(ctx)
	return nil
}
</script>

<h1>{title}</h1>
<main>{Children}</main>

Right: the title in the markup ​

html
<script lang="go">
// pages/admin/_layout.vuka.html
type Shell struct {
	Children ui.Node
}
</script>

<h1>{ui.PageTitle(ctx)}</h1>
<main>{Children}</main>

A page gives its breadcrumbs with Crumbs() []ui.Crumb, read the same way with ui.PageCrumbs(ctx); see a header that follows the page.

Wrong: a context processor variable in Load ​

html
<script lang="go">
// pages/_layout.vuka.html
type Layout struct {
	Children ui.Node
	path     string
}

func (l *Layout) Load(ctx context.Context) error {
	l.path = request.Path
	return nil
}
</script>

<small>{path}</small>
<main>{Children}</main>

Right: the variable in the markup ​

html
<script lang="go">
// pages/_layout.vuka.html
type Layout struct {
	Children ui.Node
}
</script>

<small>{request.Path}</small>
<main>{Children}</main>

A context processor variable read in the markup is tracked: on a navigation only the spots reading it render again, and the layout stays. Stored in Load, which runs once, it would keep the first page's, so the layout reloads.

A layout that does need the request (a banner keyed by a query parameter) may keep reading it; the warning says what it costs. See layouts that stay.

Released under the MIT License. Vuka builds on Go and its tools, which are made by the Go Authors. Vuka is not affiliated with Google or the Go project. Go is a trademark of Google LLC.