DioxusLabs / DioxusLabs/docsite

Document #[end_layout] attribute and layout scoping behavior

Open
#627 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
206
Forks
208
Avg merge
1h 11m
Merged PRs (30d)
3

Description

## Problem

The router documentation does not explain the stateful scoping behavior of the `#[layout()]` attribute, nor does it mention the `#[end_layout]` attribute needed to close layout scopes.

This leads to a common bug where developers accidentally create nested/duplicate layouts when trying to apply the same layout to multiple routes.

## Current Documentation Gap

The [layouts documentation](https://dioxuslabs.com/learn/0.7/essentials/router/layouts) shows only single-route examples:

```rust
#[layout(Wrapper)]
#[route("/")]
Index {},
```

When developers want multiple routes to share the same layout, they naturally assume they need to add `#[layout()]` to each route:

```rust
// ❌ Creates NESTED layouts (2 Wrapper components rendered)
#[layout(Wrapper)]
#[route("/")]
Home {},

#[layout(Wrapper)] // This NESTS inside the first layout!
#[route("/tokens")]
Tokens {},
```

This results in duplicate UI elements (e.g., 2 navigation bars, 2 headers) with no compile-time warning.

## Root Cause

The `#[layout()]` attribute creates a **persistent, stateful scope** that remains active for all subsequent routes until explicitly closed with `#[end_layout]` (similar to how `#[nest()]` works with `#[end_nest]`).

## What Should Be Documented

1. **Layout scoping is stateful** - Once opened, it affects all subsequent routes
2. **The `#[end_layout]` attribute exists** - Explicitly closes a layout scope
3. **Proper indentation convention** - Visual hierarchy helps prevent mistakes
4. **Multiple routes under one layout** - Show the correct pattern:

```rust
#[layout(Wrapper)]
#[route("/")]
Home {},

#[route("/tokens")]
Tokens {},
#[end_layout]
```

5. **Warning about duplicate layouts** - Explain what happens if scopes aren't closed
6. **Debugging technique** - Mention `cargo expand` to verify nesting levels

## Real-World Impact

This bit us in production - our `/tokens` page rendered with 2 complete layouts (duplicate navigation, duplicate sidebars) while `/` rendered correctly. Debugging required:
- Inspecting generated HTML with curl
- Using `cargo expand` to examine macro-generated code
- Reading Dioxus router source code

The fix was simple (`#[end_layout]`), but discovering it was not.

## Comparison with Nested Routes

The [nested routes documentation](https://dioxuslabs.com/learn/0.7/essentials/router/routes) **does** explain this pattern for `#[nest()]`:

> To finish a nest, we use the `#[end_nest]` attribute or the end of the enum.

Layouts should have equivalent documentation for `#[end_layout]`.

## Proposed Solution

Add a new section to the layouts documentation showing:
- How to apply one layout to multiple routes
- The `#[end_layout]` attribute
- Warning about accidental nesting
- Example of the wrong pattern vs correct pattern
- Optional: debugging tips

## References

- Tutorial code that works (but doesn't explain why): https://dioxuslabs.com/learn/0.7/tutorial/routing#adding-a-favorites-route
- Nested routes docs (good model to follow): https://dioxuslabs.com/learn/0.7/essentials/router/routes#nested-routes

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.