fix: Use Rc for lifecycle management (#4471)

* fix: Use Rc for lifecycle management

* Try to unwrap the Rc instead of using both rc and option

* Add a test for use drop

* fix test name

---------

Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
yydcnjjwandEvan Almloff authored and GitHub committed 2025-08-06 10:30:36 -05:00
1 parent 79e7739bee
commit a610aaefc3
2 files changed
+72 -9

No files matched your search

+5 -9
View File
@@ -4,6 +4,7 @@ use crate::{
Task,
};
use std::future::Future;
use std::rc::Rc;
use std::sync::Arc;
/// Get the current scope id
@@ -441,15 +442,10 @@ pub fn use_drop<D: FnOnce() + 'static>(destroy: D) {
}
}
// We need to impl clone for the lifecycle, but we don't want the drop handler for the closure to be called twice.
impl<D: FnOnce()> Clone for LifeCycle<D> {
fn clone(&self) -> Self {
Self { ondestroy: None }
}
}
use_hook(|| LifeCycle {
ondestroy: Some(destroy),
use_hook(|| {
Rc::new(LifeCycle {
ondestroy: Some(destroy),
})
});
}
+67
View File
@@ -0,0 +1,67 @@
//! Tests the use_drop hook
use dioxus::dioxus_core::use_drop;
use dioxus::prelude::*;
use std::sync::{Arc, Mutex};
type Shared<T> = Arc<Mutex<T>>;
#[derive(Clone, Props)]
struct AppProps {
render_child: Shared<bool>,
drop_count: Shared<u32>,
}
impl PartialEq for AppProps {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.drop_count, &other.drop_count)
}
}
fn app(props: AppProps) -> Element {
let render_child = props.render_child.clone();
let render_child = *render_child.lock().unwrap();
println!(
"Rendering app component with render_child: {}",
render_child
);
rsx! {
if render_child {
child_component {
drop_count: props.drop_count.clone(),
render_child: props.render_child.clone()
}
}
}
}
fn child_component(props: AppProps) -> Element {
println!("Rendering child component");
use_drop(move || {
println!("Child component is being dropped");
let mut count = props.drop_count.lock().unwrap();
*count += 1;
});
rsx! {}
}
#[test]
fn drop_runs() {
let drop_count = Arc::new(Mutex::new(0));
let render_child = Arc::new(Mutex::new(true));
let mut dom = VirtualDom::new_with_props(
app,
AppProps { drop_count: drop_count.clone(), render_child: render_child.clone() },
);
dom.rebuild_in_place();
assert_eq!(*drop_count.lock().unwrap(), 0);
*render_child.lock().unwrap() = false;
dom.mark_dirty(ScopeId::APP);
dom.render_immediate(&mut dioxus_core::NoOpMutations);
assert_eq!(*drop_count.lock().unwrap(), 1);
*render_child.lock().unwrap() = false;
}