mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 12:43:08 +00:00
fix: scopes not dropping their hooks
This commit is contained in:
parent
1737c55575
commit
69a347a551
3 changed files with 48 additions and 11 deletions
36
examples/drops.rs
Normal file
36
examples/drops.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dioxus_desktop::launch(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
let count = if cx.generation() % 2 == 0 { 10 } else { 0 };
|
||||||
|
|
||||||
|
println!("Generation: {}", cx.generation());
|
||||||
|
|
||||||
|
if cx.generation() < 10 {
|
||||||
|
cx.needs_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
render! {
|
||||||
|
(0..count).map(|_| rsx!{
|
||||||
|
Comp {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Comp(cx: Scope) -> Element {
|
||||||
|
cx.use_hook(|| Drops);
|
||||||
|
render! {
|
||||||
|
div{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Drops;
|
||||||
|
|
||||||
|
impl Drop for Drops {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
println!("Dropped!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom, AttributeValue, DynamicNode,
|
innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom,
|
||||||
ScopeId,
|
AttributeValue, DynamicNode, ScopeId,
|
||||||
};
|
};
|
||||||
use bumpalo::boxed::Box as BumpBox;
|
use bumpalo::boxed::Box as BumpBox;
|
||||||
|
|
||||||
|
@ -89,6 +89,11 @@ impl VirtualDom {
|
||||||
|
|
||||||
// Drop a scope and all its children
|
// Drop a scope and all its children
|
||||||
pub(crate) fn drop_scope(&mut self, id: ScopeId) {
|
pub(crate) fn drop_scope(&mut self, id: ScopeId) {
|
||||||
|
self.dirty_scopes.remove(&DirtyScope {
|
||||||
|
height: self.scopes[id.0].height,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
self.ensure_drop_safety(id);
|
self.ensure_drop_safety(id);
|
||||||
|
|
||||||
if let Some(root) = self.scopes[id.0].as_ref().try_root_node() {
|
if let Some(root) = self.scopes[id.0].as_ref().try_root_node() {
|
||||||
|
|
|
@ -916,29 +916,25 @@ impl<'b> VirtualDom {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_component_node(&mut self, comp: &VComponent, gen_muts: bool) {
|
fn remove_component_node(&mut self, comp: &VComponent, gen_muts: bool) {
|
||||||
|
// Remove the component reference from the vcomponent so they're not tied together
|
||||||
let scope = comp
|
let scope = comp
|
||||||
.scope
|
.scope
|
||||||
.take()
|
.take()
|
||||||
.expect("VComponents to always have a scope");
|
.expect("VComponents to always have a scope");
|
||||||
|
|
||||||
|
// Remove the component from the dom
|
||||||
match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
|
match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
|
||||||
RenderReturn::Ready(t) => self.remove_node(t, gen_muts),
|
RenderReturn::Ready(t) => self.remove_node(t, gen_muts),
|
||||||
RenderReturn::Aborted(placeholder) => self.remove_placeholder(placeholder, gen_muts),
|
RenderReturn::Aborted(placeholder) => self.remove_placeholder(placeholder, gen_muts),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Restore the props back to the vcomponent in case it gets rendered again
|
||||||
let props = self.scopes[scope.0].props.take();
|
let props = self.scopes[scope.0].props.take();
|
||||||
|
|
||||||
self.dirty_scopes.remove(&DirtyScope {
|
|
||||||
height: self.scopes[scope.0].height,
|
|
||||||
id: scope,
|
|
||||||
});
|
|
||||||
|
|
||||||
*comp.props.borrow_mut() = unsafe { std::mem::transmute(props) };
|
*comp.props.borrow_mut() = unsafe { std::mem::transmute(props) };
|
||||||
|
|
||||||
// make sure to wipe any of its props and listeners
|
// Now drop all the resouces
|
||||||
self.ensure_drop_safety(scope);
|
self.drop_scope(scope);
|
||||||
self.scopes.remove(scope.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId {
|
fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId {
|
||||||
|
|
Loading…
Reference in a new issue