scopes.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. use crate::{
  2. any_props::BoxedAnyProps, nodes::RenderReturn, runtime::Runtime, scope_context::ScopeContext,
  3. };
  4. use std::{cell::Ref, fmt::Debug, rc::Rc};
  5. /// A component's unique identifier.
  6. ///
  7. /// `ScopeId` is a `usize` that acts a key for the internal slab of Scopes. This means that the key is not unqiue across
  8. /// time. We do try and guarantee that between calls to `wait_for_work`, no ScopeIds will be recycled in order to give
  9. /// time for any logic that relies on these IDs to properly update.
  10. #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
  11. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
  12. pub struct ScopeId(pub usize);
  13. impl ScopeId {
  14. /// The root ScopeId.
  15. ///
  16. /// This scope will last for the entire duration of your app, making it convenient for long-lived state
  17. /// that is created dynamically somewhere down the component tree.
  18. ///
  19. /// # Example
  20. ///
  21. /// ```rust, ignore
  22. /// use dioxus_signals::*;
  23. /// let my_persistent_state = Signal::new_in_scope(ScopeId::ROOT, String::new());
  24. /// ```
  25. pub const ROOT: ScopeId = ScopeId(0);
  26. }
  27. /// A component's rendered state.
  28. ///
  29. /// This state erases the type of the component's props. It is used to store the state of a component in the runtime.
  30. pub struct ScopeState {
  31. pub(crate) runtime: Rc<Runtime>,
  32. pub(crate) context_id: ScopeId,
  33. pub(crate) last_rendered_node: Option<RenderReturn>,
  34. pub(crate) props: BoxedAnyProps,
  35. }
  36. impl Drop for ScopeState {
  37. fn drop(&mut self) {
  38. self.runtime.remove_context(self.context_id);
  39. }
  40. }
  41. impl ScopeState {
  42. /// Get a handle to the currently active head node arena for this Scope
  43. ///
  44. /// This is useful for traversing the tree outside of the VirtualDom, such as in a custom renderer or in SSR.
  45. ///
  46. /// Panics if the tree has not been built yet.
  47. pub fn root_node(&self) -> &RenderReturn {
  48. self.try_root_node()
  49. .expect("The tree has not been built yet. Make sure to call rebuild on the tree before accessing its nodes.")
  50. }
  51. /// Try to get a handle to the currently active head node arena for this Scope
  52. ///
  53. /// This is useful for traversing the tree outside of the VirtualDom, such as in a custom renderer or in SSR.
  54. ///
  55. /// Returns [`None`] if the tree has not been built yet.
  56. pub fn try_root_node(&self) -> Option<&RenderReturn> {
  57. self.last_rendered_node.as_ref()
  58. }
  59. pub(crate) fn context(&self) -> Ref<'_, ScopeContext> {
  60. self.runtime.get_context(self.context_id).unwrap()
  61. }
  62. }