DioxusLabs / DioxusLabs/docsite
Document #[end_layout] attribute and layout scoping behavior
- 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.