MudEngine Part 6: Multiplayer
App Component — Name Registration
The App component is the entry point. On first visit it shows a name input screen, pre-filled with the generated name. There is no persistent state yet — each page load starts fresh.
Once the player enters a name and clicks the button (or presses Enter), the Game component mounts, which establishes the WebSocket connection.
The two-component split is important: the Game component's use_websocket and use_future hooks only run after the player provides a name. This avoids connecting with an empty name.
Replace src/components/app.rs with this version. It imports the Game component and the random_name helper from the game module:
use crate::components::game::Game; use crate::game::random_name::random_name; use dioxus::prelude::*; #[component] pub fn App() -> Element { let mut player_name = use_signal(random_name); let mut registered = use_signal(|| false); rsx! { document::Stylesheet { href: asset!("/assets/main.css") } document::Stylesheet { href: asset!("/assets/dx-components-theme.css") } if !*registered.read() { div { class: "name-screen", h1 { "🧙 MudEngine" } p { class: "subtitle", "A multiplayer adventure awaits. What is your name?" } input { class: "name-input", value: "{player_name}", oninput: move |e| player_name.set(e.value()), onkeydown: move |e| { if e.key() == Key::Enter && !player_name.read().trim().is_empty() { registered.set(true); } }, placeholder: "Enter your name...", } button { class: "join-btn", onclick: move |_| { if !player_name.read().trim().is_empty() { registered.set(true); } }, "Enter the World" } } } else { Game { name: player_name() } } } }
Dioxus hooks (use_signal, use_future, use_websocket) must be called in the same order on every render. Conditional rendering that changes which hooks are called is only safe when the condition stays stable — here, once registered is true, it never flips back, so the Game component mounts exactly once.
If we tried to call use_websocket inside the same component as the name input, we'd need to conditionally skip the hook call when not registered, breaking the hook order rules. The two-component pattern avoids this cleanly.