dioxus-query

Crates.iodioxus-query
lib.rsdioxus-query
version0.8.1
created_at2023-08-05 20:26:40.674356+00
updated_at2025-06-14 16:40:05.446545+00
descriptionFully-typed, async, reusable cached state management for Dioxus 🧬
homepagehttps://github.com/marc2332/dioxus-query
repositoryhttps://github.com/marc2332/dioxus-query
max_upload_size
id936774
size192,177
Marc Espin (marc2332)

documentation

README

Discord Server

dioxus-query 🦀⚡

Fully-typed, async, reusable cached state management for Dioxus 🧬. Inspired by TanStack Query.

See the Docs or join the Discord.

Support

  • Dioxus v0.6 🧬
  • All renderers (web, desktop, freya, etc)
  • Both WASM and native targets

Features

  • Renderer-agnostic

  • Queries and Mutations

  • Fully typed, no type erasing

  • Invalidate queries manually

  • Invalidate queries on equality change

  • Concurrent execution of queries

  • Background interval re-execution of queries

  • Opt-in in-memory cache of queries results

  • Works with ReactiveContext-powered hooks like use_effect or use_memo

  • On window/tab focus invalidation

Installation

Install the latest release:

cargo add dioxus-query

Example

Run manually:

cargo run --example hello_world

Code:

#[derive(Clone)]
struct FancyClient;

impl FancyClient {
    pub fn name(&self) -> &'static str {
        "Marc"
    }
}

#[derive(Clone, PartialEq, Hash, Eq)]
struct GetUserName(Captured<FancyClient>);

impl QueryCapability for GetUserName {
    type Ok = String;
    type Err = ();
    type Keys = usize;

    async fn run(&self, user_id: &Self::Keys) -> Result<Self::Ok, Self::Err> {
        println!("Fetching name of user {user_id}");
        sleep(Duration::from_millis(650)).await;
        match user_id {
            0 => Ok(self.0.name().to_string()),
            _ => Err(()),
        }
    }
}

#[allow(non_snake_case)]
#[component]
fn User(id: usize) -> Element {
    let user_name = use_query(Query::new(id, GetUserName(Captured(FancyClient))));

    rsx!(
        p { "{user_name.read().state():?}" }
    )
}

fn app() -> Element {
    let refresh = move |_| async move {
        QueriesStorage::<GetUserName>::invalidate_matching(0).await;
    };

    rsx!(
        User { id: 0 }
        User { id: 0 }
        button { onclick: refresh, label { "Refresh" } }
    )
}

To Do

  • Tests
  • Improved documentation
  • Real-world examples

MIT License

Commit count: 58

cargo fmt