|
@@ -1,3 +1,32 @@
|
|
|
+//! Dioxus resolves scopes in a specific order to avoid unexpected behavior. All tasks are resolved in the order of height. Scopes that are higher up in the tree are resolved first.
|
|
|
+//! When a scope that is higher up in the tree is rerendered, it may drop scopes lower in the tree along with their tasks.
|
|
|
+//!
|
|
|
+//! ```rust
|
|
|
+//! use dioxus::prelude::*;
|
|
|
+//!
|
|
|
+//! fn app() -> Element {
|
|
|
+//! let vec = use_signal(|| vec![0; 10]);
|
|
|
+//! rsx! {
|
|
|
+//! // If the length of the vec shrinks we need to make sure that the children are dropped along with their tasks the new state of the vec is read
|
|
|
+//! for idx in 0..vec.len() {
|
|
|
+//! Child { idx, vec }
|
|
|
+//! }
|
|
|
+//! }
|
|
|
+//! }
|
|
|
+//!
|
|
|
+//! #[component]
|
|
|
+//! fn Child(vec: Signal<Vec<usize>>, idx: usize) -> Element {
|
|
|
+//! use_hook(|| {
|
|
|
+//! spawn(async {
|
|
|
+//! // If we let this task run after the child is dropped, it will panic.
|
|
|
+//! println!("Task {}", vec.read()[idx]);
|
|
|
+//! });
|
|
|
+//! });
|
|
|
+//!
|
|
|
+//! rsx! {}
|
|
|
+//! }
|
|
|
+//! ```
|
|
|
+
|
|
|
use crate::ScopeId;
|
|
|
use crate::Task;
|
|
|
use std::borrow::Borrow;
|
|
@@ -49,6 +78,7 @@ pub struct DirtyScopes {
|
|
|
}
|
|
|
|
|
|
impl DirtyScopes {
|
|
|
+ /// Queue a task to be polled
|
|
|
pub fn queue_task(&mut self, task: Task, order: ScopeOrder) {
|
|
|
match self.tasks.get(&order) {
|
|
|
Some(scope) => scope.queue_task(task),
|
|
@@ -60,22 +90,27 @@ impl DirtyScopes {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// Queue a scope to be rerendered
|
|
|
pub fn queue_scope(&mut self, order: ScopeOrder) {
|
|
|
self.scopes.insert(order);
|
|
|
}
|
|
|
|
|
|
+ /// Check if there are any dirty scopes
|
|
|
pub fn has_dirty_scopes(&self) -> bool {
|
|
|
!self.scopes.is_empty()
|
|
|
}
|
|
|
|
|
|
+ /// Take any tasks from the highest scope
|
|
|
pub fn pop_task(&mut self) -> Option<DirtyTasks> {
|
|
|
self.tasks.pop_first()
|
|
|
}
|
|
|
|
|
|
+ /// Take the highest scope that needs to be rerendered
|
|
|
pub fn pop_scope(&mut self) -> Option<ScopeOrder> {
|
|
|
self.scopes.pop_first()
|
|
|
}
|
|
|
|
|
|
+ /// Take any work from the highest scope. This may include rerunning the scope and/or running tasks
|
|
|
pub fn pop_work(&mut self) -> Option<Work> {
|
|
|
let dirty_scope = self.scopes.first();
|
|
|
let dirty_task = self.tasks.first();
|