AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Dioxus State Management

skill-bwbioinfo-skill-dioxus-dioxus-state-management · by bwbioinfo

Manage application state in Dioxus using signals, stores, context, and global state patterns. Use when implementing reactive state, sharing data between components, or building complex state architectures.

No reviews yet
0 installs
22 views
0.0% view→install

Install

$ agentstack add skill-bwbioinfo-skill-dioxus-dioxus-state-management

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bwbioinfo-skill-dioxus-dioxus-state-management)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Dioxus State Management? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Dioxus State Management

This skill helps you implement effective state management in Dioxus applications using signals, stores, context providers, and global state patterns.

When to use this skill

  • Managing local component state with reactive updates
  • Sharing state between components and component hierarchies
  • Implementing global application state management
  • Building complex state architectures with stores and context
  • Optimizing state updates and preventing unnecessary re-renders
  • Handling async state and data fetching patterns

Core State Management Concepts

1. Local State with Signals

Basic Signal Usage:

#![allow(non_snake_case)]
use dioxus::prelude::*;

#[component]
fn Counter() -> Element {
    let mut count = use_signal(|| 0);
    
    rsx! {
        div {
            class: "counter",
            h2 { "Count: {count}" }
            button {
                onclick: move |_| count += 1,
                "Increment"
            }
            button {
                onclick: move |_| count -= 1,
                "Decrement"
            }
            button {
                onclick: move |_| count.set(0),
                "Reset"
            }
        }
    }
}

Complex State Objects:

#[derive(Clone, Debug, PartialEq)]
struct UserProfile {
    name: String,
    email: String,
    avatar_url: Option,
    preferences: UserPreferences,
}

#[derive(Clone, Debug, PartialEq)]
struct UserPreferences {
    theme: Theme,
    notifications: bool,
    language: String,
}

#[component]
fn UserProfileEditor() -> Element {
    let mut profile = use_signal(|| UserProfile {
        name: String::new(),
        email: String::new(),
        avatar_url: None,
        preferences: UserPreferences {
            theme: Theme::Light,
            notifications: true,
            language: "en".to_string(),
        },
    });
    
    rsx! {
        div {
            class: "profile-editor",
            h2 { "Edit Profile" }
            
            input {
                r#type: "text",
                placeholder: "Name",
                value: "{profile().name}",
                oninput: move |evt| {
                    profile.write().name = evt.value();
                }
            }
            
            input {
                r#type: "email",
                placeholder: "Email",
                value: "{profile().email}",
                oninput: move |evt| {
                    profile.write().email = evt.value();
                }
            }
            
            div {
                class: "preferences",
                h3 { "Preferences" }
                
                label {
                    input {
                        r#type: "checkbox",
                        checked: profile().preferences.notifications,
                        onchange: move |evt| {
                            profile.write().preferences.notifications = evt.checked();
                        }
                    }
                    "Enable notifications"
                }
                
                select {
                    value: "{profile().preferences.theme:?}",
                    onchange: move |evt| {
                        profile.write().preferences.theme = match evt.value().as_str() {
                            "Dark" => Theme::Dark,
                            _ => Theme::Light,
                        };
                    },
                    option { value: "Light", "Light Theme" }
                    option { value: "Dark", "Dark Theme" }
                }
            }
            
            button {
                onclick: move |_| {
                    save_profile(profile());
                },
                "Save Profile"
            }
        }
    }
}

2. Derived State with use_memo

Computed Values:

#[component]
fn ShoppingCart() -> Element {
    let mut items = use_signal(|| Vec::::new());
    
    // Derived state - automatically updates when items change
    let total_items = use_memo(move || {
        items().iter().map(|item| item.quantity).sum::()
    });
    
    let total_price = use_memo(move || {
        items().iter()
            .map(|item| item.price * item.quantity as f64)
            .sum::()
    });
    
    let has_items = use_memo(move || !items().is_empty());
    
    rsx! {
        div {
            class: "shopping-cart",
            h2 { "Shopping Cart" }
            
            if has_items() {
                div {
                    class: "cart-summary",
                    p { "Items: {total_items}" }
                    p { "Total: ${total_price:.2}" }
                }
                
                div {
                    class: "cart-items",
                    for item in items() {
                        CartItemComponent {
                            key: "{item.id}",
                            item: item.clone(),
                            on_quantity_change: move |item_id, new_quantity| {
                                items.write().iter_mut()
                                    .find(|i| i.id == item_id)
                                    .map(|i| i.quantity = new_quantity);
                            },
                            on_remove: move |item_id| {
                                items.write().retain(|i| i.id != item_id);
                            }
                        }
                    }
                }
                
                button {
                    class: "checkout-btn",
                    onclick: move |_| checkout(items()),
                    "Checkout (${total_price:.2})"
                }
            } else {
                div {
                    class: "empty-cart",
                    p { "Your cart is empty" }
                }
            }
        }
    }
}

3. Context-Based State Sharing

Authentication Context:

#[derive(Clone)]
pub struct AuthContext {
    pub user: Signal>,
    pub is_loading: Signal,
    pub error: Signal>,
    pub login: Callback,
    pub logout: Callback,
    pub register: Callback,
}

#[component]
pub fn AuthProvider(children: Element) -> Element {
    let mut user = use_signal(|| None::);
    let mut is_loading = use_signal(|| false);
    let mut error = use_signal(|| None::);
    
    let login = use_callback(move |(email, password): (String, String)| {
        let user = user.clone();
        let is_loading = is_loading.clone();
        let error = error.clone();
        
        spawn(async move {
            is_loading.set(true);
            error.set(None);
            
            match authenticate(&email, &password).await {
                Ok(user_data) => {
                    user.set(Some(user_data));
                    store_session_token().await;
                }
                Err(e) => {
                    error.set(Some(e.to_string()));
                }
            }
            
            is_loading.set(false);
        });
    });
    
    let logout = use_callback(move |_| {
        let user = user.clone();
        spawn(async move {
            clear_session_token().await;
            user.set(None);
        });
    });
    
    let register = use_callback(move |registration: UserRegistration| {
        let user = user.clone();
        let is_loading = is_loading.clone();
        let error = error.clone();
        
        spawn(async move {
            is_loading.set(true);
            error.set(None);
            
            match create_user(&registration).await {
                Ok(user_data) => {
                    user.set(Some(user_data));
                }
                Err(e) => {
                    error.set(Some(e.to_string()));
                }
            }
            
            is_loading.set(false);
        });
    });
    
    let context = AuthContext {
        user,
        is_loading,
        error,
        login,
        logout,
        register,
    };
    
    use_context_provider(|| context);
    
    rsx! { {children} }
}

#[component]
fn LoginForm() -> Element {
    let auth = use_context::();
    let mut email = use_signal(|| String::new());
    let mut password = use_signal(|| String::new());
    
    let handle_submit = move |_| {
        auth.login.call((email(), password()));
    };
    
    rsx! {
        form {
            class: "login-form",
            onsubmit: handle_submit,
            
            if let Some(error) = auth.error() {
                div {
                    class: "error-message",
                    "{error}"
                }
            }
            
            input {
                r#type: "email",
                placeholder: "Email",
                value: "{email}",
                oninput: move |evt| email.set(evt.value()),
                disabled: auth.is_loading()
            }
            
            input {
                r#type: "password",
                placeholder: "Password",
                value: "{password}",
                oninput: move |evt| password.set(evt.value()),
                disabled: auth.is_loading()
            }
            
            button {
                r#type: "submit",
                disabled: auth.is_loading(),
                if auth.is_loading() {
                    "Logging in..."
                } else {
                    "Login"
                }
            }
        }
    }
}

#[component]
fn UserProfile() -> Element {
    let auth = use_context::();
    
    match auth.user() {
        Some(user) => rsx! {
            div {
                class: "user-profile",
                h2 { "Welcome, {user.name}!" }
                p { "Email: {user.email}" }
                button {
                    onclick: move |_| auth.logout.call(()),
                    "Logout"
                }
            }
        },
        None => rsx! {
            div {
                class: "not-authenticated",
                p { "Please log in to view your profile." }
            }
        }
    }
}

4. Global State with Stores

Application Store:

use dioxus_stores::*;

#[derive(Default, Store)]
struct AppStore {
    theme: Theme,
    user_preferences: UserPreferences,
    notifications: Vec,
    ui_state: UiState,
}

#[derive(Default)]
struct UiState {
    sidebar_open: bool,
    modal_stack: Vec,
    loading_states: HashMap,
}

#[derive(Clone)]
enum StoreAction {
    SetTheme(Theme),
    ToggleSidebar,
    AddNotification(Notification),
    RemoveNotification(String),
    SetLoading(String, bool),
    OpenModal(ModalType),
    CloseModal,
}

impl AppStore {
    fn reduce(&mut self, action: StoreAction) {
        match action {
            StoreAction::SetTheme(theme) => {
                self.theme = theme;
            }
            StoreAction::ToggleSidebar => {
                self.ui_state.sidebar_open = !self.ui_state.sidebar_open;
            }
            StoreAction::AddNotification(notification) => {
                self.notifications.push(notification);
            }
            StoreAction::RemoveNotification(id) => {
                self.notifications.retain(|n| n.id != id);
            }
            StoreAction::SetLoading(key, loading) => {
                if loading {
                    self.ui_state.loading_states.insert(key, true);
                } else {
                    self.ui_state.loading_states.remove(&key);
                }
            }
            StoreAction::OpenModal(modal) => {
                self.ui_state.modal_stack.push(modal);
            }
            StoreAction::CloseModal => {
                self.ui_state.modal_stack.pop();
            }
        }
    }
}

#[component]
fn App() -> Element {
    let mut store = use_store(AppStore::default);
    
    rsx! {
        div {
            class: "app",
            class: match store.theme {
                Theme::Light => "light-theme",
                Theme::Dark => "dark-theme",
            },
            
            Header {
                store: store.clone(),
            }
            
            div {
                class: "main-content",
                class: if store.ui_state.sidebar_open { "sidebar-open" } else { "sidebar-closed" },
                
                Sidebar {
                    store: store.clone(),
                    open: store.ui_state.sidebar_open,
                }
                
                MainContent {
                    store: store.clone(),
                }
            }
            
            NotificationCenter {
                notifications: store.notifications.clone(),
                on_dismiss: move |id| {
                    store.write().reduce(StoreAction::RemoveNotification(id));
                }
            }
            
            ModalStack {
                modals: store.ui_state.modal_stack.clone(),
                on_close: move |_| {
                    store.write().reduce(StoreAction::CloseModal);
                }
            }
        }
    }
}

5. Async State Management

Data Fetching with Resources:

#[component]
fn UserList() -> Element {
    let mut users_resource = use_resource(|| async {
        fetch_users().await
    });
    
    let mut search_query = use_signal(|| String::new());
    let mut filter_role = use_signal(|| None::);
    
    // Refetch when filters change
    use_effect(move || {
        let query = search_query();
        let role = filter_role();
        
        users_resource.restart();
    });
    
    rsx! {
        div {
            class: "user-list",
            
            div {
                class: "filters",
                input {
                    r#type: "text",
                    placeholder: "Search users...",
                    value: "{search_query}",
                    oninput: move |evt| search_query.set(evt.value())
                }
                
                select {
                    onchange: move |evt| {
                        filter_role.set(match evt.value().as_str() {
                            "admin" => Some(UserRole::Admin),
                            "user" => Some(UserRole::User),
                            _ => None,
                        });
                    },
                    option { value: "", "All Roles" }
                    option { value: "admin", "Admin" }
                    option { value: "user", "User" }
                }
                
                button {
                    onclick: move |_| users_resource.restart(),
                    "Refresh"
                }
            }
            
            match users_resource() {
                Some(Ok(users)) => rsx! {
                    div {
                        class: "users-grid",
                        for user in users {
                            UserCard {
                                key: "{user.id}",
                                user: user.clone()
                            }
                        }
                    }
                },
                Some(Err(e)) => rsx! {
                    div {
                        class: "error-state",
                        h3 { "Failed to load users" }
                        p { "{e}" }
                        button {
                            onclick: move |_| users_resource.restart(),
                            "Try Again"
                        }
                    }
                },
                None => rsx! {
                    div {
                        class: "loading-state",
                        div { class: "spinner" }
                        p { "Loading users..." }
                    }
                }
            }
        }
    }
}

Optimistic Updates:

#[component]
fn TodoItem(todo: Todo, on_update: Callback) -> Element {
    let mut is_updating = use_signal(|| false);
    let mut optimistic_todo = use_signal(|| todo.clone());

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [bwbioinfo](https://github.com/bwbioinfo)
- **Source:** [bwbioinfo/skill_dioxus](https://github.com/bwbioinfo/skill_dioxus)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.