Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use_resource cancels spawn_forever's future (and even regular spawn) when listening to signals set by said future #2235

Closed
1 of 3 tasks
TapGhoul opened this issue Apr 3, 2024 · 4 comments · Fixed by #2236
Assignees
Labels
bug Something isn't working consistency improve cohesiveness of features signals Related to the signals crate
Milestone

Comments

@TapGhoul
Copy link

TapGhoul commented Apr 3, 2024

Problem

When setting a signal in a spawn_forever() (and even a regular spawn(), or component async fn), if it is also used by a resource, it cancels the future erroneously.

Steps To Reproduce

Note: gloo_timers here is just as a simple await point, this occurs with server functions and all other operations that yield to the async runtime.
Steps to reproduce the behavior:

#[component]
fn Broken() -> Element {
    let signal = use_signal(|| false);
    let _future = use_resource(move || async move { signal() });
    let action = move |_| {
        spawn_forever(async move {
            let d = DropDetector;
            let mut signal = signal.clone();
            log::info!("Start of signal set");
            signal.set(true);
            log::info!("Set to true");
            gloo_timers::future::sleep(Duration::from_millis(500)).await;
            log::info!("Timer finished");
            signal.set(false);
            log::info!("Signal set to false");
            drop(d);
        });
    };

    rsx! {
        div {
            div { "State: {signal}" }
            button { onclick: action, "press me" }
        }
    }
}

struct DropDetector;
impl Drop for crate::DropDetector {
    fn drop(&mut self) {
        log::warn!("Dropped DropDetector!");
    }
}

Expected behavior

  • Page: "State: false"
  • Press button
  • Log: "Start of signal set"
  • Log: "Set to true"
  • Page: "State: true"
  • [pause]
  • Log: "Timer finished"
  • Log: "Signal set to false"
  • Log: "Dropped DropDetector!"
  • Page: "State: false"

Resulting behavior

  • Page: "State: false"
  • Press button
  • Log: "Start of signal set"
  • Log: "Set to true"
  • Log: "Dropped DropDetector!"
  • Page: "State: true"

Environment:

  • Dioxus version: Git 11bf5ae (fix firefox refreshing loop in debug mode)
  • Rust version: 1.77.1
  • OS info: Linux
  • 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
@TapGhoul
Copy link
Author

TapGhoul commented Apr 3, 2024

Worth a note: this was encountered at first when doing loading screen stuff with server functions and use_server_future() - but this is a more minimal and targeted sample. The broken bit is unrelated to server fns.

@TapGhoul
Copy link
Author

TapGhoul commented Apr 4, 2024

@jkelleyrtp it seems the bug is not fixed. Tested with git 821a650, same test code as above.

@jkelleyrtp jkelleyrtp reopened this Apr 5, 2024
@jkelleyrtp jkelleyrtp added this to the 0.6.0 milestone Jul 25, 2024
@jkelleyrtp jkelleyrtp added signals Related to the signals crate consistency improve cohesiveness of features bug Something isn't working labels Jul 31, 2024
@jkelleyrtp
Copy link
Member

Sorry for the delay - we've put in many fixes regarding async since April and I think this might already be fixed - but I'll let @ealmloff double check.

@ealmloff
Copy link
Member

ealmloff commented Aug 1, 2024

This updated version of the example reproduction works:

// [dependencies]
// dioxus = { path = "/Users/evanalmloff/Desktop/Github/dioxus/packages/dioxus", features = ["web"] }
// dioxus-logger = "0.5.1"
// gloo-timers = { version = "0.3.0", features = ["futures"] }
// tracing = "0.1.40"

use std::time::Duration;

use dioxus::prelude::*;
use tracing::Level;

fn main() {
    dioxus_logger::init(Level::TRACE).unwrap();
    launch(Broken)
}

#[component]
fn Broken() -> Element {
    let signal = use_signal(|| false);
    let _future = use_resource(move || async move { signal() });
    let action = move |_| {
        spawn_forever(async move {
            let d = DropDetector;
            let mut signal = signal.clone();
            tracing::info!("Start of signal set");
            signal.set(true);
            tracing::info!("Set to true");
            gloo_timers::future::sleep(Duration::from_millis(500)).await;
            tracing::info!("Timer finished");
            signal.set(false);
            tracing::info!("Signal set to false");
            drop(d);
        });
    };

    rsx! {
        div {
            div { "State: {signal}" }
            button { onclick: action, "press me" }
        }
    }
}

struct DropDetector;
impl Drop for crate::DropDetector {
    fn drop(&mut self) {
        tracing::warn!("Dropped DropDetector!");
    }
}

@ealmloff ealmloff closed this as completed Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working consistency improve cohesiveness of features signals Related to the signals crate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants