dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

MountedData does not properly being updated after rerendering.

Open ArtBlnd opened this issue 1 year ago • 3 comments

Problem

MountedData is the structure that provides get_client_rect function to get position and size of the element. It can be stored somewhere by cloning Rc<MountedData> from the onmounted callback. The Rc<MountedData> should point exact same element or the onmounted callback should be called after the re-render

Steps To Reproduce

  • Use onmounted and store MountedData somewhere else.
  • Try re-render the element
  • Call MountedData::get_clinet_rect() function. It will cause panic.

Expected behavior

The stored Rc<MountedData> should return values properly. or the callback registered on the onmounted should called after re-rendering.

Environment:

  • Dioxus version: 0.5.1
  • Rust version: 1.77.2
  • OS info: Windows
  • App platform: Desktop

Questionnaire

  • [x] 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

ArtBlnd avatar May 16 '24 09:05 ArtBlnd

I found something weird on the desktop build. I think in the desktop build, onmounted callback does not being invoked sometimes.

ArtBlnd avatar May 16 '24 10:05 ArtBlnd

Note there is a difference between rerendering a component and rerendering an element. An element should only be recreated when you switch to a new rsx block. If you rerun the component, but return the same rsx block then the element should not be recreated and the onmounted event should not trigger again

In the following code, toggle will recreate the element and trigger the event. It seems to work as I would expect. Can you identify anything different your code does differently that may be triggering the issue?

#![allow(non_snake_case)]
use std::time::Duration;
use dioxus::prelude::*;

fn main() {
    launch(app)
}

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

    use_future(move || async move {
        loop {
            tokio::time::sleep(Duration::from_millis(100)).await;
            count += 1
        }
    });

    if toggle() {
        rsx! {
            button {
                onclick: move |_| toggle.toggle(),
                "toggle"
            }
            div {
                onmounted: move |evt| {
                    async move {
                        loop {
                            tokio::time::sleep(Duration::from_millis(100)).await;
                            println!("{:?}", evt.get_client_rect().await);
                        }
                    }
                },
                width: "{count}px",
                height: "{count}px",
                style: "background-color: red",
            }
        }
    }
    else {
        rsx! {
            button {
                onclick: move |_| toggle.toggle(),
                "toggle"
            }
            div {
                onmounted: move |evt| {
                    async move {
                        loop {
                            tokio::time::sleep(Duration::from_millis(100)).await;
                            println!("{:?}", evt.get_client_rect().await);
                        }
                    }
                },
                width: "{count}px",
                height: "{count}px",
                style: "background-color: red",
            }
        }
    }
}

ealmloff avatar May 16 '24 13:05 ealmloff

I do not recreate element itself but I do reposition it on the parent. Maybe that causes the problem.

ArtBlnd avatar May 16 '24 13:05 ArtBlnd