memo.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use crate::read::Readable;
  2. use crate::write::Writable;
  3. use dioxus_core::prelude::*;
  4. use generational_box::Storage;
  5. use crate::dependency::Dependency;
  6. use crate::use_signal;
  7. use crate::{signal::SignalData, ReadOnlySignal, Signal};
  8. /// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes.
  9. ///
  10. /// Selectors can be used to efficiently compute derived data from signals.
  11. ///
  12. /// ```rust
  13. /// use dioxus::prelude::*;
  14. /// use dioxus_signals::*;
  15. ///
  16. /// fn App() -> Element {
  17. /// let mut count = use_signal(|| 0);
  18. /// let double = use_memo(move || count * 2);
  19. /// count += 1;
  20. /// assert_eq!(double.value(), count * 2);
  21. ///
  22. /// rsx! { "{double}" }
  23. /// }
  24. /// ```
  25. #[track_caller]
  26. pub fn use_memo<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<R> {
  27. use_maybe_sync_memo(f)
  28. }
  29. /// Creates a new Selector that may be sync. The selector will be run immediately and whenever any signal it reads changes.
  30. ///
  31. /// Selectors can be used to efficiently compute derived data from signals.
  32. ///
  33. /// ```rust
  34. /// use dioxus::prelude::*;
  35. /// use dioxus_signals::*;
  36. ///
  37. /// fn App(cx: Scope) -> Element {
  38. /// let mut count = use_signal(cx, || 0);
  39. /// let double = use_memo(cx, move || count * 2);
  40. /// count += 1;
  41. /// assert_eq!(double.value(), count * 2);
  42. ///
  43. /// render! { "{double}" }
  44. /// }
  45. /// ```
  46. #[track_caller]
  47. pub fn use_maybe_sync_memo<R: PartialEq, S: Storage<SignalData<R>>>(
  48. f: impl FnMut() -> R + 'static,
  49. ) -> ReadOnlySignal<R, S> {
  50. use_hook(|| Signal::maybe_sync_memo(f))
  51. }
  52. /// Creates a new unsync Selector with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
  53. ///
  54. /// Selectors can be used to efficiently compute derived data from signals.
  55. ///
  56. /// ```rust
  57. /// use dioxus::prelude::*;
  58. /// use dioxus_signals::*;
  59. ///
  60. /// fn App(cx: Scope) -> Element {
  61. /// let mut local_state = use_state(cx, || 0);
  62. /// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2);
  63. /// local_state.set(1);
  64. ///
  65. /// render! { "{double}" }
  66. /// }
  67. /// ```
  68. #[track_caller]
  69. pub fn use_memo_with_dependencies<R: PartialEq, D: Dependency>(
  70. dependencies: D,
  71. f: impl FnMut(D::Out) -> R + 'static,
  72. ) -> ReadOnlySignal<R>
  73. where
  74. D::Out: 'static,
  75. {
  76. use_maybe_sync_selector_with_dependencies(dependencies, f)
  77. }
  78. /// Creates a new Selector that may be sync with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
  79. ///
  80. /// Selectors can be used to efficiently compute derived data from signals.
  81. ///
  82. /// ```rust
  83. /// use dioxus::prelude::*;
  84. /// use dioxus_signals::*;
  85. ///
  86. /// fn App(cx: Scope) -> Element {
  87. /// let mut local_state = use_state(cx, || 0);
  88. /// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2);
  89. /// local_state.set(1);
  90. ///
  91. /// render! { "{double}" }
  92. /// }
  93. /// ```
  94. #[track_caller]
  95. pub fn use_maybe_sync_selector_with_dependencies<
  96. R: PartialEq,
  97. D: Dependency,
  98. S: Storage<SignalData<R>>,
  99. >(
  100. dependencies: D,
  101. mut f: impl FnMut(D::Out) -> R + 'static,
  102. ) -> ReadOnlySignal<R, S>
  103. where
  104. D::Out: 'static,
  105. {
  106. let mut dependencies_signal = use_signal(|| dependencies.out());
  107. let selector = use_hook(|| {
  108. Signal::maybe_sync_memo(move || {
  109. let deref = &*dependencies_signal.read();
  110. f(deref.clone())
  111. })
  112. });
  113. let changed = { dependencies.changed(&*dependencies_signal.read()) };
  114. if changed {
  115. dependencies_signal.set(dependencies.out());
  116. }
  117. selector
  118. }