MudEngine Part 4: Single-Player Dioxus GUI
The Grid component
The WorldGrid component renders the 9 rooms as a 3×3 CSS grid. It takes a ReadSignal<World> prop so it reactively reads the world state.
Each cell shows the room name. The room the player currently occupies is highlighted in blue. The other rooms are dimmed — the player can see the full map but knows where they are at a glance.
Add this component below the World impl block.
#[component] fn WorldGrid(world: ReadSignal<World>) -> Element { let w = world.read(); let player_room = w.player_room; let names: Vec<String> = w.rooms.iter().map(|r| r.name.clone()).collect(); drop(w); rsx! { div { class: "world-grid", for (idx, name) in names.iter().enumerate() { if idx == player_room { div { key: "{idx}", class: "cell active", "{name}" } } else { div { key: "{idx}", class: "cell", "{name}" } } } } } }
ReadSignal<World> is a prop type that wraps any reactive source (a Signal<World>, a Memo<World>, or another ReadSignal). The component calls .read() to get a Ref<World> — a guarded reference that Dioxus tracks as a dependency.
When the parent writes to the original Signal<World> (e.g., world.write().go("north")), all components that read that signal via .read() automatically re-render.
We call .read() once, clone what we need (the room names), then drop(w) to release the borrow guard before entering the rsx! block. This avoids holding a borrow across the for loop.