MountedData does not properly being updated after rerendering.
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
I found something weird on the desktop build. I think in the desktop build, onmounted callback does not being invoked sometimes.
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",
}
}
}
}
I do not recreate element itself but I do reposition it on the parent. Maybe that causes the problem.