#Signal writes + infinite loops - scenarios

1 messages ยท Page 1 of 1 (latest)

grand copper
#

I am not sure about basics.. when having this example

pub fn App() -> Element {
    let mut name = use_signal(|| "bob".to_string());

    rsx! {
        input {
            // we tell the component what to render
            value: "{name}",
            // and what to do when the value changes
            oninput: move |event| name.set(event.value())
        }
    }
}

oninput does change name (which is signal), it rerenders the component on each change -> the new changed name is printed into the value -> which would trigger oninput -> and cycling....

It's obviously not happening, but why exactly?
Is it because the value: {name} is not changed by the component rerender, because it's already in the "state" of the value that it would be changed into? But I am just guessing...

I would like to be prepared for a cycling situations, which I am surprisingly thinking a lot about, when learning the Dioxus - my head is spinning in the "ok, it rerenders the component, but i am also setting the value... it rerenders.. " ๐Ÿ™‚

honest wind
#

That's not correct

#

oninput will only fire on user input

#

if you change the value manually in any way, it will not fire oninput

#

Only the user by actually pressing the keybord can fire it

#

๐Ÿ˜„

grand copper
#

Ok, thanks. And in general... how often have you had a problem with rerendering?

honest wind
#

What kind of problem do you mean?

#

best thing to do is to always try not update when it's not needed

#

that's about it

grand copper
#

While learning and playing with code.. this for example fires "rerendering"

pub fn Component(n: i32) -> Element {
    let mut search = use_signal(|| "asd".to_string());
    info!("search: {}", search);
    search.set("asd2".to_string());
    rsx! {}
}

I am reading and writing...
I am just thinking in general this must happen a lot.. but maybe I am wrong.

peak lake
#

Generally you should try to avoid writing to state in the body of a component (the PR above also adds warnings about this)

honest wind
#

๐Ÿ‘†๐Ÿป

grand copper
#

I am sorry for another question... I have read the issue, but the first code example has new message Consider writing to the signal in an effect
And the second code example does use effect and seems like it's also considered bad, not working?
I don't get it now.. is use_effect a solution how to write to a value safely or not, please?

peak lake
#

Components, effects, memos, and resources each have thier own a reactive scopes

#

Reactive scopes rerun when any signal you read inside of them are changed

#

In the first example,

fn app() -> Element {
    let mut count = use_signal(|| 0);
    // Write in the component reactive scope
    count += 1;

    rsx! {
        // "{count}" reads in the same component reactive scope
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| count += 1, "Up high!" }
        button { onclick: move |_| count -= 1, "Down low!" }
    }
}
#

In the second example,

use_effect(move || {
    // Read in the effect reactive scope
    println!("Counter changed to {count}");
    // Write in the same effect reactive scope
    count += 1;
});
honest wind
#

soo, try not to write and read in the same reactive scope or there will be a high change that you end up in an infinite loop heh

peak lake
#

You can fix the issue by either:

  1. Writing and reading to different signals
    Change this:
#[derive(Clone, Copy)]
struct Counts {
    count1: i32,
    count2: i32,
}

fn app() -> Element {
    let mut counts = use_signal(|| Counts { count1: 0, count2: 0 });
    
    use_effect(move ||{
        counts.write().count1 = counts().count2;
    })
}

To this:

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

    use_effect(move || {
        count1.write(count2());
    });
}
#
  1. Writing in different scopes
    Change this:
fn app() -> Element {
    let mut count = use_signal(|| 0);

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

To this:

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

    use_effect(move || {
        count.write(count());
    });
    use_effect(move || {
        println!("{}", count());
    });
}
grand copper
#

Excelent.. thanks a lot!

Btw, when playing with this code, it's not infinetly logging (to console), wonder why.

pub fn app(n: i32) -> Element {
    let mut count = use_signal(|| 0);
    // info!("count: {count}");
    use_effect(move || {
        info!("effect: {count}");
        count += 1;
    });

    rsx! {}

It starts to infinetly log, spam the console, when I uncomment the commented line.

#

With the commented line, it prints this... something like "until 13", and stops there, on each refresh. Is it spinning, infinite, behind the scene?

honest wind
#

perhaps it's too fast that the web hangs up?

grand copper
#

But. theoretically it just spins inside the Scope of use_effect, right?

honest wind
#

Well, yes, but it's still spinning nonetheless

#

it's all running under 1 thread

grand copper
#

Btw, the MessageEvent lines... why are they there? ๐Ÿ™‚

peak lake
peak lake