atom_ref.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use crate::{use_atom_root, AtomId, AtomRef, AtomRoot, Readable};
  2. use dioxus_core::{ScopeId, ScopeState};
  3. use std::{
  4. cell::{Ref, RefCell, RefMut},
  5. rc::Rc,
  6. };
  7. ///
  8. ///
  9. ///
  10. ///
  11. ///
  12. ///
  13. ///
  14. ///
  15. pub fn use_atom_ref<T: 'static>(cx: &ScopeState, atom: AtomRef<T>) -> &UseAtomRef<T> {
  16. let root = use_atom_root(cx);
  17. &cx.use_hook(|| {
  18. root.initialize(atom);
  19. (
  20. UseAtomRef {
  21. ptr: atom.unique_id(),
  22. root: root.clone(),
  23. scope_id: cx.scope_id(),
  24. value: root.register(atom, cx.scope_id()),
  25. },
  26. AtomRefSubscription {
  27. ptr: atom.unique_id(),
  28. root: root.clone(),
  29. scope_id: cx.scope_id(),
  30. },
  31. )
  32. })
  33. .0
  34. }
  35. pub struct AtomRefSubscription {
  36. ptr: AtomId,
  37. root: Rc<AtomRoot>,
  38. scope_id: ScopeId,
  39. }
  40. impl Drop for AtomRefSubscription {
  41. fn drop(&mut self) {
  42. self.root.unsubscribe(self.ptr, self.scope_id)
  43. }
  44. }
  45. pub struct UseAtomRef<T> {
  46. ptr: AtomId,
  47. value: Rc<RefCell<T>>,
  48. root: Rc<AtomRoot>,
  49. scope_id: ScopeId,
  50. }
  51. impl<T> Clone for UseAtomRef<T> {
  52. fn clone(&self) -> Self {
  53. Self {
  54. ptr: self.ptr,
  55. value: self.value.clone(),
  56. root: self.root.clone(),
  57. scope_id: self.scope_id,
  58. }
  59. }
  60. }
  61. impl<T: 'static> UseAtomRef<T> {
  62. pub fn read(&self) -> Ref<T> {
  63. self.value.borrow()
  64. }
  65. /// This is silent operation
  66. /// call `.force_update()` manually if required
  67. pub fn with_mut_silent(&self, cb: impl FnOnce(&mut T)) {
  68. cb(&mut *self.write_silent())
  69. }
  70. pub fn write(&self) -> RefMut<T> {
  71. self.root.force_update(self.ptr);
  72. self.value.borrow_mut()
  73. }
  74. /// Silent write to AtomRef
  75. /// does not update Subscribed scopes
  76. pub fn write_silent(&self) -> RefMut<T> {
  77. self.value.borrow_mut()
  78. }
  79. /// Replace old value with new one
  80. pub fn set(&self, new: T) {
  81. self.root.force_update(self.ptr);
  82. self.root.set(self.ptr, new);
  83. }
  84. /// Do not update provided context on Write ops
  85. /// Example:
  86. /// ```ignore
  87. /// static ATOM_DATA: AtomRef<Collection> = |_| Default::default();
  88. /// fn App(cx: Scope) {
  89. /// use_init_atom_root(cx);
  90. /// let atom_data = use_atom_ref(cx, ATOM_DATA);
  91. /// atom_data.unsubscribe(cx);
  92. /// atom_data.write().update();
  93. /// }
  94. /// ```
  95. pub fn unsubscribe(&self, cx: &ScopeState) {
  96. self.root.unsubscribe(self.ptr, cx.scope_id());
  97. }
  98. /// Force update of subscribed Scopes
  99. pub fn force_update(&self) {
  100. self.root.force_update(self.ptr);
  101. }
  102. }