dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

Resource does not restart from async event handler

Open luveti opened this issue 1 year ago • 1 comments

use dioxus::prelude::*;

pub fn main() {
    launch(app)
}

pub fn app() -> Element {
    let mut num = use_server_future(get_next_number);

    rsx! {
        div {
            // This does work
            // onclick: move |e| {
            //     if let Some(num) = &mut num {
            //         num.restart();
            //     }
            // },
            // This does not work
            onclick: move |e| async move {
                if let Some(num) = &mut num {
                    num.restart();
                }
            },
            if let Some(num) = num {
                match num.value().as_ref() {
                    Some(num) => match num.as_ref() {
                        Ok(num) => rsx! { p { "Next number is {num}" } },
                        Err(e) => rsx! { p { "Loading next number failed, {e}" } },
                    },
                    None =>  rsx! { p { "Loading..." } }
                }
            }
        }
    }
}

#[server]
async fn get_next_number() -> Result<u32, ServerFnError> {
    static mut NUM: u32 = 0;
    unsafe {
        NUM += 1;
        Ok(NUM)
    }
}

Environment:

  • Dioxus version: master
  • Rust version: nightly
  • OS info: NixOS
  • App platform: fullstack

Questionnaire

  • [ ] I'm interested in fixing this myself but don't know where to start
  • [ ] I would like to fix and I have a solution
  • [ ] I don't have time to fix this right now, but maybe later

luveti avatar May 23 '24 07:05 luveti

Poking around a bit, it looks like using the following works:

pub fn app() -> Element {
    let mut num = use_server_future(get_next_number);

    rsx! {
        div {
            onclick: move |e| async move {
                queue_effect(move || {
                    if let Some(num) = &mut num {
                        num.restart();
                    }
                });
            },
            if let Some(num) = num {
                match num.value().as_ref() {
                    Some(num) => match num.as_ref() {
                        Ok(num) => rsx! { p { "Next number is {num}" } },
                        Err(e) => rsx! { p { "Loading next number failed, {e}" } },
                    },
                    None =>  rsx! { p { "Loading..." } }
                }
            }
        }
    }
}

Is this the recommended work around? If so, this may be a nice addition to the Event Handlers page.

luveti avatar May 23 '24 07:05 luveti

Fixed in https://github.com/DioxusLabs/dioxus/pull/2488

ealmloff avatar Jul 17 '24 00:07 ealmloff