#Do signals trigger from external sources?

54 messages · Page 1 of 1 (latest)

fluid sequoia
#

I've been working on integrating signals into dioxus-spring and I have this weird issue using this new hook. Animations work great using this code in the crate examples, but writing to the signal from dioxus-use-gesture (which uses custom event handlers) doesn't. Both crates worked before the update but now only spring does 🤔 This is the hook minus the funky type desc:

let spring_ref = use_spring_ref(cx, from, f);
to_owned![spring_ref];

let signal: Signal<Option<(V, Option<Duration>)>> = use_signal(cx, || None);

dioxus_signals::use_effect(cx, move || {
    // Not being called with 'static event handlers
    // Called with dioxus listeners

    if let Some((to, duration_cell)) = &*signal.read() {
        if let Some(duration) = duration_cell {
            spring_ref.animate(to.clone(), *duration);
        } else {
            spring_ref.set(to.clone());
        }
    }
});

UseSpringSignal { signal }
honest rover
#

What part of the code doesn't work?

#

Is the effect not reruning when you write to the signal? Does spring_ref.set not trigger updates? Or does writing to the signal you return panic?

fluid sequoia
#

Sorry I know it's pretty vague I'm still kinda confused with signals so idk how to narrow it down much

#

Basically this hook is a wrapper around that spring_ref with a signal so I can use copy

#

The problem I'm having is use_effect isn't being called in some cases. Everything works when I use dioxus event handlers to write to the signal but when I manually create html event listeners the effect isn't being triggered. The value does update though and if I remove the use_effect it works (but causes too many re-renders)

honest rover
#

That helps a lot narrowing it down 🙂

#

Does this work:

let spring_ref = use_spring_ref(cx, from, f);
to_owned![spring_ref];

let signal: Signal<Option<(V, Option<Duration>)>> = use_signal(cx, || None);

use_effect(cx, (signal.read().clone(),), move |(signal_value,)| {
    // Not being called with 'static event handlers
    // Called with dioxus listeners

    if let Some((to, duration_cell)) = signal_value {
        if let Some(duration) = duration_cell {
            spring_ref.animate(to.clone(), *duration);
        } else {
            spring_ref.set(to.clone());
        }
    }
});

UseSpringSignal { signal }
#

It could be an issue with the signal version of use effect

fluid sequoia
#

I actually did try that and it worked but again it caused the component to re-render

#

Is it weird using the signals use_effect doesn't do that? It's definitely what I want but I'm not sure how it works

honest rover
#

Dioxus has a global runtime while you are in the virtual dom that makes signals work

#

I wonder if it isn't active when you write to the signal in a web-sys event handler...

#

I should be active until the application is closed on the web

fluid sequoia
#

Ah man I figured from the docs but then I'm not sure how I would do this

#

That's interesting I'm guessing this is more of an edge case. I could make a branch if you wanted to play with it

honest rover
#

Oh I forgot I changed it so that it is only set when diffing, running Dioxus event handlers, and futures

honest rover
#

I think I have a fix...

fluid sequoia
honest rover
#

In the git version of Dioxus the Runtime is public

fluid sequoia
#

Oh wait I think I misunderstood, so dioxus_signal::use_effect won't re-render the component? If that's the intended behaviour that solution would be perfect!

honest rover
#

use_effect reruns seperately from the component

fluid sequoia
#

Cool! I'm gonna try that out rn

#

Nope 😦 still doesn't update

#

I just updated the branch with the guards in place if you wanna make sure it's not me

honest rover
#

Actually the web-sys closure code you have looks fine

#

It doesn't seem like you would call a signal from inside of there

#

I need to go now, but I can take another look in a few hours

fluid sequoia
#

Whenever you get time I know it's a mess in there so FYI the handler that's being called is where I access the signal in the example

honest rover
#

I took a look at the signals branch and the signals example but I'm not sure what is wrong with it

#

When I hover over the text a number is logged that increases and decreses to the right numbers

#

And it only renders the component once

#

Is it missing some animation frames?

fluid sequoia
#

Oh sorry it's the drag example in use-gesture

#

That's my curiosity though those examples in spring work

#

For me use-gesture only updates once even though I've logged the signal being written to

honest rover
#

Sorry I cloned the wrong link

#

The use gesture example seems to work for me as well

#

Oh wrong branch on the use spring repo

honest rover
#

This definitely seems like a bug with signal subscriptions

fluid sequoia
#

Huh ok thanks for looking into it

#

I really thought not having the runtime available would've been the issue. Do signals somehow need a local scope or something else?

honest rover
#

It looks like dioxus is looking for the signal context and doesn't find it

#

It can't find it because it doesn't know what scope you are trying to read from

#

This should fix it:

dioxus = { git = "https://github.com/ealmloff/dioxus", branch = "fix-signals-outside-of-runtime" }
#

You also don't need the runtime guards any more

fluid sequoia
#

Works like a dream! Thanks for all the help 🎉