rustrust-tokiodioxus

Dioxus - spawn not getting executed


I'm building a desktop app with Dioxus 0.5, but in my components it seems like the "spawn" function is not executing the async block inside of it. It doesn't give errors, and compiles fine, but clicking the button does not have the desired effect. Other methods, such as doing "use_future" or returning a Future from an event handler, work fine. However, the docs do show the use of spawn in this situation.

Here is a component where spawn isn't working:

use crate::logic::models::{Gender, Publisher};
use crate::logic::publishers_service;
use crate::AppState;
use dioxus::prelude::*;

#[component]
pub fn AddPublisherForm(onsubmit: EventHandler<()>) -> Element {
    let onsubmit = move |evt: Event<FormData>| {
        let vals = evt.data.values();
        let name = vals.get("name");

        let gender_string = vals.get("gender").unwrap().as_value();
        let gender = match gender_string.as_str() {
            "m" => Gender::Male,
            "f" => Gender::Female,
            _ => Gender::Male,
        };

        let suspended = vals.get("suspended").is_some();

        if name.is_none() {
            return ();
        }

        let name = name.unwrap().as_value();
        let state = use_context::<Signal<AppState>>();

        println!("Creating user");

        spawn(async move {
            println!("Inside spawn");
            publishers_service::create(
                Publisher {
                    id: None,
                    name: name.clone(),
                    gender,
                    suspended,
                },
                &state(),
            )
            .await;
        });

        onsubmit.call(());
    };

    rsx! {
        div {
            form {
                onsubmit: onsubmit,

                fieldset {
                    legend {
                        "Add publiser"
                    },

                    input {
                        name: "name"
                    },

                    "male",

                    input {
                        r#type: "radio",
                        name: "gender",
                        value: "m",
                        checked: true
                    },

                    "female",

                    input {
                        r#type: "radio",
                        name: "gender",
                        value: "f",
                        checked: false
                    }

                    "suspended",
                    input {
                        r#type: "checkbox",
                        name: "suspended",
                        checked: false
                    }

                    button {
                        "create"
                    }
                }
            }
        }
    }
}

On submitting, I see the messages "Creating user" and "Refreshing publishers" (from the onsubmit callback in the parent element), but not "Inside spawn", and the user is not created, even though the method on the service is correct (and was working previously, when I was using "use_future")

I don't know if this is important (I would imagine it isn't) but here is something I'm doing in the main file to prepare the database connection before launching the Dioxus app:


#[derive(Clone)]
pub struct AppState {
    connection: Pool<Sqlite>,
}

fn main() -> Result<()> {
    let rt = Runtime::new().unwrap();
    let handle = rt.handle();

    let db = handle.block_on(async { create_db().await });

    let state = AppState { connection: db };

    launch_app(state);

    Ok(())
}

And this is the code that launches the app:

pub fn launch_app(state: AppState) {
    // Init logger
    dioxus_logger::init(Level::INFO).expect("failed to init logger");

    LaunchBuilder::desktop()
        .with_cfg(
            Config::default()
                .with_custom_head("<link href=\"./base.css\" rel=\"stylesheet\">".to_string())
                .with_menu(None),
        )
        .with_context(state)
        .launch(App);
}

Why is the "spawn" function not working, even though it seems like this is how you're supposed to use it?


Solution

  • Based on your code, I simplified it a bit just to have a cleaner space, tested and it's working.
    You can find the sample code here.

    And this is the result:

    screenshot

    Hope it helps!