#unresponsive signals

1 messages · Page 1 of 1 (latest)

whole barn
#

any ideas on why my signals arent signaling?

let mut internal_x = use_signal(|| None);
use_effect(move || log::log!(log::Level::Info, "x is {:?}", internal_x()));
use_effect(move || match eval() {
        Some(mut eval) => {
            let (cancel_sender, mut cancel_receiver) = oneshot::channel();
            cancel_main_future.set(Some(cancel_sender));

            spawn(async move {
                loop {
                    select! {
                        _ = cancel_receiver => return,
                        result = eval.recv().fuse() => {
                            log::log!(log::Level::Info,"{result:?}");
                            let value = result.unwrap();
                            let data: RawScrollData = serde_json::from_value(value).unwrap();

                            if data.x.is_some() {
                                log::log!(log::Level::Info,"x");

                                internal_x.set(data.x);
                            }

it is sending the log for "x" so it should be setting the signal, but the log in the first use_effect stops triggering

#

i have another use_effect thats acting strangely as well

use_effect(move || {
        log!(
            log::Level::Info,
            "\nx: {:?}\ny: {:?}\nis_scrolling: {:?}\narrived_state: {:?}\ndirections: {:?}",
            x.read(),
            y.read(),
            is_scrolling.read(),
            arrived_state.read(),
            directions.read(),
        )
    });

it stops logging as the other one, but if i read x in onclick it causes the effect to run

onclick: move |e| log!(log::Level::Info,"{:?}", x())
#

actually it seems like when i use it in the onclick it causes all the use_effect to trigger

whole barn
#

so i found out the problem to this

#

its the fact that effects only run on renders

lean fossil
#

that's not the issue

#

I think that signals mutated from async tasks do not mark scopes as dirty

whole barn
#

they do according to tracing

#

iirc

lean fossil
#

where is the other chat we were talking?

#

nvm #general

#

damn discord

#
fn app() -> Element {
    let mut count = use_signal(|| 0);

    use_effect(move || {
        println!("{}", count);
    });

    println!("rerunning");

    rsx!(
        Button {
            onclick: move |_| count += 1,
            label { "Increase" }
        }
        Button {
            onclick: |_| needs_update(),
            label { "rerun" }
        }
    )
}
#

This works just fine

whole barn
#

the onclick triggers a render

lean fossil
#

No, it doesn't

whole barn
#

it does

lean fossil
#

But this doesn't work


fn app() -> Element {
    let mut count = use_signal(|| 0);

    use_effect(move || {
        println!("{}", count());
    });

    use_hook(move || {
        spawn(async move {
            loop {
                sleep(Duration::from_secs(1)).await;
                count += 1
            }
        })
    });

    rsx!(
        Button {
            onclick: move |_| println!("{}", count()),
            label { "read" }
        }
        Button {
            onclick: |_| needs_update(),
            label { "rerun" }
        }
    )
}
lean fossil
#

It would only trigger a rerender if the signal was read in the component function

#

which is not the case, it's only being read in the effect

lean fossil
#

The problem is when you mutate the signal from an async task

whole barn
# lean fossil Nope

does

    use_hook(|| {
        spawn(async {
            loop {
                wait_for_next_render().await;
                log::info!("click")
            }
        })
    });

    rsx! {
        button {
            onclick: |_| ()
        }
    }
#

at least counts for whatever that function counts as a render

lean fossil
#

that's not render

whole barn
#

well its what the function calls a render so

lean fossil
whole barn
#

and what use_effect uses

lean fossil
#
 use_hook(|| {
    spawn(async {
        loop {
            wait_for_next_render().await;
            log::info!("click")
        }
    })
});

log::info!("render")

rsx! {
    button {
        onclick: |_| ()
    }
}
#

render is when the actual component function runs

#

async tasks are not render

whole barn
#

btw i didnt mean component render

#

any render

#

and events count apparently

#

at least click events

#

though actually that probably means its a bug

#

to be more exact next time the runtime renders

lean fossil
#

components render

#

anything else aren't renders

lean fossil
whole barn
#

i think the runtime render is basically when it does anything non async

lean fossil
whole barn
#

yeah what about it?

lean fossil
#

The component isn't rerendering

#

yet the effect is running

whole barn
#

the reason that works is still because of the button triggering wait_for_next_render

lean fossil
#

hence effects don't need their components to rerender in order to run

whole barn
#

anything that triggers wait_for_next_render causes it to update

lean fossil
#

In any case

#

ReactiveContext::current() doesn't seem to be available in async tasks?

whole barn
#
#[track_caller]
pub fn use_effect(callback: impl FnMut() + 'static) -> Effect {
    // let mut run_effect = use_hook(|| CopyValue::new(true));
    // use_hook_did_run(move |did_run| run_effect.set(did_run));

    let callback = use_callback(callback);

    let location = std::panic::Location::caller();

    use_hook(|| {
        let (rc, mut changed) = ReactiveContext::new_with_origin(location);
        spawn(async move {
            loop {
                // Run the effect
                rc.run_in(&*callback);

                // Wait for context to change
                let _ = changed.next().await;

                // Wait for the dom the be finished with sync work
                wait_for_next_render().await;
            }
        });
        Effect { rc }
    })
}
#

theres the use_effect definition

lean fossil
#

That could be the reason why mutated signals aren't doing any check at all for their subs

whole barn
#

if you remove wait_for_next_render().await; it triggers from my issue example

#

so if its what you are saying then the bug/problem would be that thats not getting triggered

#

wait_for_next_render

#

it is at the very least marking scopes as dirty according to tracing when i checked

#

yeah looking at it theres dirty scope checks everywhere that should trigger work

#

did you try out my issue example?

#

nvm

#

just to make sure, the bug here would be the spawned futures signal not triggering wait_for_next_render

lean fossil
#

can't see the issue and damn tracing doesn't seem to work for me for whatever reason 🤣

whole barn
#

if you comment out wait_for_next_render().await; it works

whole barn
#

also web or desktop?

lean fossil
#

What is dioxus logging?

#

I am neither on web or desktop, I was on freya

whole barn
#

ah

#

this thing dioxus_logger::init(LevelFilter::Info).expect("failed to init logger");

lean fossil
#

I was creating an tracing subscriber

whole barn
#

wondering since if you use that then setting a tracing subscriber will error

lean fossil
#

it just froze the app for somer reason

whole barn
#

oh

#

thats bad

lean fossil
#

Yeah idk

#

could be a big log or something like that

whole barn
#

it shouldnt be that bad

#

unless you are testing on some mega project

lean fossil
#

now that I think about it

#

it could be my fault

#

yeah, got it working now

#

mm

#

render_immediate is only called when there are actual DOM mutations

#

So the effect will only run when there are DOM mutations

whole barn
#

if the wait_for_work future returns right?

lean fossil
#

Nope

#

wait_for_work won't do much here

#

that only polls the VirtualDOM

whole barn
#

well its also an implementation difference

#

depending on platform

lean fossil
#

What truly matters is that effects are subscribed to render_signal and render_signal is only triggered when render_immediate is called, which only happens when there is at least 1 mutation in the DOM

whole barn
#

on web it seems to run whenever wait_for_work returns

lean fossil
#

fn app() -> Element {
    let mut count = use_signal(|| 0);

    use_effect(move || {
        println!("Count: {}", count());
    });

    use_hook(move || {
        spawn(async move {
            loop {
                sleep(Duration::from_secs(1)).await;
                count += 1
            }
        })
    });

    rsx!(
        div {
            onclick: move |_| println!("{}", count()),
            p { "read" }
        }
        OtherComp { }
    )
}

#[allow(non_snake_case)]
fn OtherComp() -> Element {
    let mut other_count = use_signal(|| 0);
    rsx!(
        div {
            onclick: move |_| other_count += 1,
            p { "{other_count}" }
        }
    )
}
#

does this work for you?

#

adapt it to whatever your platform is

whole barn
#

gotta figure out how to sleep on web then

lean fossil
#

Forget about this lol

whole barn
#

well i certainly managed to lock up my browser

lean fossil
#

xD

whole barn
#

any idea how to kill an infinite loop in web?

#

100% cpu lol

#

ok yeah i totally failed at a sleep, getting so many messages

#

holy shit that must have made a memory leak

#

got a system memory popup

#

ok i cant get it to sleep